@@ -174,6 +174,16 @@ minecraft {
174174 // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
175175 args ' --mod' , mod_id, ' --all' , ' --output' , file(' src/generated/resources/' ), ' --existing' , file(' src/main/resources/' )
176176 }
177+
178+ [' Fresh' , ' Reload' ]. each { String phase ->
179+ create(" surfaceIntegration${ phase} " ) {
180+ parent runs. server
181+ workingDirectory layout. buildDirectory. dir(' surface-integration-run' ). get(). asFile
182+ property ' forge.logging.console.level' , ' info'
183+ property ' surfaceprobe.integrationPhase' , phase. toLowerCase(Locale . ROOT )
184+ args ' --nogui'
185+ }
186+ }
177187 }
178188}
179189
@@ -278,6 +288,84 @@ tasks.named('test', Test).configure {
278288 useJUnitPlatform()
279289}
280290
291+ def surfaceIntegrationClasses = layout. buildDirectory. dir(' surface-integration-fixture/classes' )
292+ def compileSurfaceIntegrationTestMod = tasks. register(' compileSurfaceIntegrationTestMod' , JavaCompile ) {
293+ dependsOn tasks. named(' classes' )
294+ source fileTree(' src/biomeIntegrationTest/java' )
295+ classpath = files(sourceSets. main. output, sourceSets. main. compileClasspath)
296+ destinationDirectory. set(surfaceIntegrationClasses)
297+ javaCompiler. set(javaToolchains. compilerFor {
298+ languageVersion = JavaLanguageVersion . of(17 )
299+ })
300+ options. release = 17
301+ options. encoding = ' UTF-8'
302+ }
303+
304+ def surfaceIntegrationTestModJar = tasks. register(' surfaceIntegrationTestModJar' , Jar ) {
305+ dependsOn compileSurfaceIntegrationTestMod
306+ archiveFileName = ' surfaceprobe.jar'
307+ destinationDirectory = layout. buildDirectory. dir(' surface-integration-fixture' )
308+ from surfaceIntegrationClasses
309+ from ' src/biomeIntegrationTest/resources'
310+ }
311+
312+ def surfaceIntegrationRunDirectory = layout. buildDirectory. dir(' surface-integration-run' )
313+ def prepareSurfaceIntegrationTest = tasks. register(' prepareSurfaceIntegrationTest' ) {
314+ dependsOn surfaceIntegrationTestModJar
315+ doLast {
316+ File runDirectory = surfaceIntegrationRunDirectory. get(). asFile
317+ delete runDirectory
318+ runDirectory. mkdirs()
319+ copy {
320+ from surfaceIntegrationTestModJar. flatMap { it. archiveFile }
321+ into surfaceIntegrationRunDirectory. map { it. dir(' mods' ) }
322+ }
323+ new File (runDirectory, ' server.properties' ). setText(''' \
324+ level-name=surface-integration-world
325+ level-seed=0
326+ level-type=minecraft:normal
327+ online-mode=false
328+ allow-nether=true
329+ generate-structures=false
330+ spawn-protection=0
331+ max-tick-time=-1
332+ ''' , ' UTF-8' )
333+ new File (runDirectory, ' eula.txt' ). setText(' eula=true\n ' , ' UTF-8' )
334+ }
335+ }
336+
337+ tasks. configureEach {
338+ if (name == ' runSurfaceIntegrationFresh' ) {
339+ dependsOn prepareSurfaceIntegrationTest
340+ } else if (name == ' runSurfaceIntegrationReload' ) {
341+ dependsOn ' runSurfaceIntegrationFresh'
342+ }
343+ }
344+
345+ def surfaceIntegrationTest = tasks. register(' surfaceIntegrationTest' ) {
346+ group = ' verification'
347+ description = ' Verifies provider surfaces and dynamic-biome geology across fresh and reloaded normal terrain.'
348+ dependsOn ' runSurfaceIntegrationReload'
349+ doLast {
350+ File marker = surfaceIntegrationRunDirectory. get(). file(
351+ ' surface-integration-world/surfaceprobe-integration.properties' ). asFile
352+ if (! marker. isFile()) {
353+ throw new GradleException (" Surface integration completion marker is missing: ${ marker} " )
354+ }
355+ Properties result = new Properties ()
356+ marker. withInputStream { result. load(it) }
357+ if (result. getProperty(' reload_verified' ) != ' true' ) {
358+ throw new GradleException (" Surface integration reload was not verified: ${ marker} " )
359+ }
360+ logger. lifecycle(' Provider surfaces and dynamic-biome geology verified: {} dimensions, {} columns each, fresh + reload' ,
361+ result. getProperty(' dimensions' ), result. getProperty(' columns_per_dimension' ))
362+ }
363+ }
364+
365+ tasks. named(' check' ) {
366+ dependsOn surfaceIntegrationTest
367+ }
368+
281369// Keep every Eclipse launch input on Buildship's physical Gradle cache. Command-line
282370// verification may deliberately use a separate cache, which must not leak into Eclipse.
283371def syncEclipseRunClasspaths = tasks. register(' syncEclipseRunClasspaths' ) {
@@ -454,6 +542,7 @@ def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
454542 }
455543
456544 int changedLaunches = 0
545+ int changedTestExclusions = 0
457546 if (eclipseLaunchDir. isDirectory()) {
458547 File eclipseClasses = file(' bin/main' ). canonicalFile
459548 String modClasses = " ${ mod_id} %%${ eclipseClasses.absolutePath} "
@@ -471,6 +560,27 @@ def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
471560 / < mapEntry key= " MOD_CLASSES" value= " [^" ]* " \/ >/) {
472561 " < mapEntry key= \" MOD_CLASSES\" value=\" ${ modClasses} \" />"
473562 }
563+ String excludeTestKey = ' org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE'
564+ String excludeTestAttribute =
565+ " <booleanAttribute key=\" ${ excludeTestKey} \" value=\" true\" />"
566+ String beforeTestExclusion = synced
567+ if (synced. contains(" key=\" ${ excludeTestKey} \" " )) {
568+ synced = synced. replaceFirst(
569+ / < booleanAttribute key= " org\. eclipse\. jdt\. launching\. ATTR_EXCLUDE_TEST_CODE" value= " [^" ]* " \/ >/,
570+ excludeTestAttribute)
571+ } else {
572+ int launchHeaderEnd = synced.indexOf('\n ', synced.indexOf('<launchConfiguration'))
573+ if (launchHeaderEnd < 0) {
574+ throw new GradleException(" Malformed Eclipse Java launch configuration : ${launchFile}" )
575+ }
576+ String lineSeparator = synced.contains('\r\n ') ? '\r\n ' : '\n '
577+ synced = " ${synced. substring(0 , launchHeaderEnd + 1 )}" +
578+ " ${excludeTestAttribute}${lineSeparator}" +
579+ synced.substring(launchHeaderEnd + 1)
580+ }
581+ if (beforeTestExclusion != synced) {
582+ changedTestExclusions++
583+ }
474584 if (original != synced) {
475585 launchFile.setText(synced, 'UTF-8')
476586 changedLaunches++
@@ -496,7 +606,7 @@ def syncEclipseRunClasspaths = tasks.register('syncEclipseRunClasspaths') {
496606 changedLaunchGroups++
497607 }
498608 }
499- 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)" )
609+ 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)" )
500610 }
501611}
502612
0 commit comments