@@ -13,6 +13,7 @@ val pluginVersion = version.toString()
1313val paper26_1Version = " 26.1.2.build.74-stable"
1414val paper26_2Version = " 26.2.build.56-alpha"
1515val craftEngineVersion = " 26.7.2"
16+ val sparrowHeartVersion = " 0.72"
1617
1718val paper26_2CompileClasspath = configurations.create(" paper26_2CompileClasspath" ) {
1819 isCanBeConsumed = false
@@ -35,6 +36,7 @@ dependencies {
3536 compileOnly(files(" common/lib/LightAPI-fork-3.5.2.jar" ))
3637
3738 implementation(" net.momirealms:sparrow-yaml:1.0.7" )
39+ implementation(" net.momirealms:sparrow-heart:$sparrowHeartVersion " )
3840
3941 testImplementation(platform(" org.junit:junit-bom:5.13.4" ))
4042 testImplementation(" org.junit.jupiter:junit-jupiter" )
@@ -113,7 +115,7 @@ val compilePaper26_2 = tasks.register<JavaCompile>("compilePaper26_2") {
113115}
114116
115117val verifyPaperOnlyArchitecture = tasks.register(" verifyPaperOnlyArchitecture" ) {
116- description = " Rejects reintroduction of NMS, Armor Stands, or legacy compatibility layers."
118+ description = " Confines NMS reflection to the client pickup bridge and rejects legacy layers."
117119 group = LifecycleBasePlugin .VERIFICATION_GROUP
118120 val sources = sourceSets.main.get().allJava
119121 inputs.files(sources)
@@ -136,9 +138,16 @@ val verifyPaperOnlyArchitecture = tasks.register("verifyPaperOnlyArchitecture")
136138 " getPluginLoader()" ,
137139 " .spigot()" ,
138140 )
141+ val pickupBridge = file(
142+ " common/src/main/java/com/loohp/interactionvisualizer/integration/packet/ClientPickupAnimationBridge.java" ,
143+ ).canonicalFile
144+ val bridgeTokens = setOf (" net.minecraft" , " org.bukkit.craftbukkit" )
139145 val violations = sources.files.flatMap { source ->
140146 val text = source.readText()
141- forbidden.filter(text::contains).map { token -> " ${source.relativeTo(rootDir)} : $token " }
147+ forbidden.filter(text::contains).mapNotNull { token ->
148+ val allowed = source.canonicalFile == pickupBridge && token in bridgeTokens
149+ if (allowed) null else " ${source.relativeTo(rootDir)} : $token "
150+ }
142151 }
143152 check(violations.isEmpty()) {
144153 " Paper-only architecture violations:\n ${violations.joinToString(" \n " )} "
@@ -194,6 +203,7 @@ tasks.named<ShadowJar>("shadowJar") {
194203 mergeServiceFiles()
195204
196205 relocate(" net.momirealms.sparrow.yaml" , " com.loohp.interactionvisualizer.libs.sparrow.yaml" )
206+ relocate(" net.momirealms.sparrow.heart" , " com.loohp.interactionvisualizer.libs.sparrow.heart" )
197207
198208 isPreserveFileTimestamps = false
199209 isReproducibleFileOrder = true
@@ -208,6 +218,26 @@ tasks.named<ShadowJar>("shadowJar") {
208218 " CraftEngine must remain compileOnly, but provider classes were bundled:\n " +
209219 bundledCraftEngine.joinToString(" \n " )
210220 }
221+ check(jar.getEntry(" com/loohp/interactionvisualizer/libs/sparrow/heart/SparrowHeart.class" ) != null ) {
222+ " The shaded Sparrow Heart runtime is missing"
223+ }
224+ listOf (" r26_1" , " r26_2" ).forEach { adapter ->
225+ check(jar.getEntry(
226+ " com/loohp/interactionvisualizer/libs/sparrow/heart/impl/$adapter /Heart.class" ,
227+ ) != null ) {
228+ " The shaded Sparrow Heart $adapter adapter is missing"
229+ }
230+ }
231+ val unrelocatedHeart = jar.entries().asSequence()
232+ .map { it.name }
233+ .filter { it.startsWith(" net/momirealms/sparrow/heart/" ) }
234+ .toList()
235+ check(unrelocatedHeart.isEmpty()) {
236+ " Unrelocated Sparrow Heart classes were bundled:\n " + unrelocatedHeart.joinToString(" \n " )
237+ }
238+ check(jar.getEntry(" META-INF/licenses/sparrow-heart.txt" ) != null ) {
239+ " The Sparrow Heart MIT license notice is missing"
240+ }
211241 }
212242 }
213243}
0 commit comments