diff --git a/build.gradle.kts b/build.gradle.kts index 31792a80c..7caf01168 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,3 @@ -import com.volmit.nmstools.NMSToolsExtension -import com.volmit.nmstools.NMSToolsPlugin import de.undercouch.gradle.tasks.download.Download import xyz.jpenilla.runpaper.task.RunServer import kotlin.system.exitProcess @@ -30,7 +28,6 @@ buildscript { plugins { java `java-library` - alias(libs.plugins.shadow) alias(libs.plugins.download) alias(libs.plugins.runPaper) } @@ -78,14 +75,14 @@ val nmsBindings = mapOf( "v1_20_R1" to "1.20.1-R0.1-SNAPSHOT", ) val jvmVersion = mapOf() -nmsBindings.forEach { key, value -> +nmsBindings.forEach { (key, value) -> project(":nms:$key") { apply() - apply() - extensions.configure(NMSToolsExtension::class) { + nmsBinding { jvm = jvmVersion.getOrDefault(key, 21) version = value + type = NMSBinding.Type.DIRECT } dependencies { @@ -112,14 +109,18 @@ nmsBindings.forEach { key, value -> } } +dependencies { + for (key in nmsBindings.keys) { + implementation(project(":nms:$key", "reobf")) + } + implementation(project(":core", "shadow")) + implementation(project(":core:agent")) +} + tasks { jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE - nmsBindings.forEach { key, _ -> - from(project(":nms:$key").tasks.named("remap").map { zipTree(it.outputs.files.singleFile) }) - } - from(project(":core").tasks.shadowJar.flatMap { it.archiveFile }.map { zipTree(it) }) - from(project(":core:agent").tasks.jar.flatMap { it.archiveFile }) + from(configurations.runtimeClasspath.map { it.resolve().map(::zipTree) }) archiveFileName.set("Iris-${project.version}.jar") } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index c94238170..192a8ab77 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,11 +1,16 @@ plugins { - kotlin("jvm") version "2.0.20" + kotlin("jvm") version embeddedKotlinVersion } repositories { mavenCentral() + gradlePluginPortal() + maven("https://jitpack.io") } dependencies { implementation("org.ow2.asm:asm:9.8") + implementation("com.github.VolmitSoftware:NMSTools:c88961416f") + implementation("io.papermc.paperweight:paperweight-userdev:2.0.0-beta.18") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/NMSBinding.kt b/buildSrc/src/main/kotlin/NMSBinding.kt new file mode 100644 index 000000000..38419db16 --- /dev/null +++ b/buildSrc/src/main/kotlin/NMSBinding.kt @@ -0,0 +1,170 @@ +import NMSBinding.Type +import com.volmit.nmstools.NMSToolsExtension +import com.volmit.nmstools.NMSToolsPlugin +import io.papermc.paperweight.userdev.PaperweightUser +import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension +import io.papermc.paperweight.userdev.PaperweightUserExtension +import io.papermc.paperweight.userdev.attribute.Obfuscation +import io.papermc.paperweight.util.constants.REOBF_CONFIG +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.gradle.api.* +import org.gradle.api.attributes.Bundling +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.LibraryElements +import org.gradle.api.attributes.Usage +import org.gradle.api.model.ObjectFactory +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.extensions.core.extra +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.gradle.jvm.toolchain.JavaToolchainService +import javax.inject.Inject + +class NMSBinding : Plugin { + override fun apply(target: Project): Unit = with(target) { + val config = extra["nms"] as? Config ?: throw GradleException("No NMS binding configuration found") + val jvm = config.jvm + val type = config.type + + if (type == Type.USER_DEV) { + plugins.apply(PaperweightUser::class.java) + dependencies.extensions.findByType(PaperweightUserDependenciesExtension::class.java) + ?.paperDevBundle(config.version) + + val java = extensions.findByType(JavaPluginExtension::class.java) ?: throw GradleException("Java plugin not found") + java.toolchain.languageVersion.set(JavaLanguageVersion.of(jvm)) + + val javaToolchains = project.extensions.getByType(JavaToolchainService::class.java) ?: throw GradleException("Java toolchain service not found") + extensions.configure(PaperweightUserExtension::class.java) { + it.javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) + } + } else { + extra["nmsTools.useBuildTools"] = type == Type.BUILD_TOOLS + plugins.apply(NMSToolsPlugin::class.java) + extensions.configure(NMSToolsExtension::class.java) { + it.jvm.set(jvm) + it.version.set(config.version) + } + + configurations.register(REOBF_CONFIG) { conf -> + conf.isCanBeConsumed = true + conf.isCanBeResolved = false + conf.attributes { + it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) + it.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY)) + it.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR)) + it.attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL)) + it.attribute(Obfuscation.OBFUSCATION_ATTRIBUTE, objects.named(Obfuscation.OBFUSCATED)) + } + conf.outgoing.artifact(tasks.named("remap")) + } + } + + tasks.register("convert", ConversionTask::class.java, type) + val tasks = gradle.startParameter.taskNames + tasks.addFirst("$path:convert") + gradle.startParameter.setTaskNames(tasks) + } + + @CacheableTask + open class ConversionTask @Inject constructor(type: Type, ) : DefaultTask() { + private val pattern: Regex + private val replacement: String + + init { + group = "nms" + inputs.property("type", type) + outputs.file("dummy") + if (type == Type.USER_DEV) { + pattern = "org\\.bukkit\\.craftbukkit\\.${project.name}".toRegex() + replacement = "org.bukkit.craftbukkit" + } else { + pattern = "org\\.bukkit\\.craftbukkit\\.(?!${project.name})".toRegex() + replacement = "org.bukkit.craftbukkit.${project.name}." + } + } + + @TaskAction + fun process() { + val java = project.extensions.findByType(JavaPluginExtension::class.java) ?: throw GradleException("Java plugin not found") + val source = java.sourceSets.findByName("main")?.allJava ?: throw GradleException("No main source set found") + val dispatcher = Dispatchers.IO.limitedParallelism(16) + runBlocking { + for (file in source) { + if (file.extension !in listOf("java")) + continue + + + launch(dispatcher) { + val output = ArrayList() + var changed = false + + file.useLines { + for (line in it) { + if (line.startsWith("package") || line.isBlank()) { + output += line + continue + } + + if (!line.startsWith("import")) { + if (!changed) return@launch + else { + output += line + continue + } + } + + if (!line.contains(pattern)) { + output += line + continue + } + + output += line.replace(pattern, replacement) + changed = true + } + + + } + + if (changed) { + file.writer().use { + val iterator = output.iterator() + while (iterator.hasNext()) { + it.append(iterator.next()) + if (iterator.hasNext()) + it.append(NEW_LINE) + } + } + } + } + } + } + } + } + + enum class Type { + USER_DEV, + BUILD_TOOLS, + DIRECT, + } +} + +private val NEW_LINE = System.lineSeparator() + + +class Config( + var jvm: Int = 21, + var type: Type = Type.DIRECT +) { + lateinit var version: String +} + +fun Project.nmsBinding(action: Config.() -> Unit) { + extra["nms"] = Config().apply(action) + plugins.apply(NMSBinding::class.java) +} + +private inline fun ObjectFactory.named(name: String): T = named(T::class.java, name) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 718870da5..b4be6da17 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,5 @@ org.gradle.jvmargs=-Xmx3072m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF org.gradle.caching=true org.gradle.configureondemand=false -nmsTools.useBuildTools=false nmsTools.repo-url=https://repo.codemc.org/repository/nms/ nmsTools.specialSourceVersion=1.11.4 \ No newline at end of file