Initial commit
This commit is contained in:
12
gradle-project-plugin/build.gradle.kts
Normal file
12
gradle-project-plugin/build.gradle.kts
Normal file
@@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
id("de.siphalor.smcmtk.plugin")
|
||||
}
|
||||
|
||||
description = "This is the main plugin providing utilities through a Gradle extension."
|
||||
|
||||
gradlePlugin {
|
||||
val projectPlugin by plugins.creating {
|
||||
id = "de.siphalor.minecraft-modding-toolkit.project-plugin"
|
||||
implementationClass = "de.siphalor.minecraft_modding_toolkit.gradle.project_plugin.SmcmtkProjectPlugin"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.siphalor.minecraft_modding_toolkit.gradle.project_plugin
|
||||
|
||||
import net.fabricmc.loom.api.LoomGradleExtensionAPI
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.MinimalExternalModuleDependency
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
class SmcmtkLoomProxy(val project: Project, loomGradleExtensionApi: Any) {
|
||||
val logger = lazy { Logging.getLogger(javaClass) }
|
||||
val loom = loomGradleExtensionApi as LoomGradleExtensionAPI
|
||||
|
||||
fun configureOfficialMojangMappings(parchment: Provider<MinimalExternalModuleDependency>?) {
|
||||
if (parchment == null) {
|
||||
project.dependencies.add("mappings", loom.officialMojangMappings())
|
||||
} else {
|
||||
project.dependencies.add("mappings", loom.layered { layered ->
|
||||
layered.officialMojangMappings()
|
||||
layered.parchment(parchment.map { it.artifact { artifact -> artifact.type = "zip" } })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun createRemapConfiguration(sourceSet: SourceSet) {
|
||||
loom.createRemapConfigurations(sourceSet)
|
||||
}
|
||||
|
||||
fun setAccessWidenerPath(file: RegularFile) {
|
||||
loom.accessWidenerPath.set(file)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package de.siphalor.minecraft_modding_toolkit.gradle.project_plugin
|
||||
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
|
||||
abstract class SmcmtkProjectExtension(private val smcmtkProjectPlugin: SmcmtkProjectPlugin) {
|
||||
abstract val mcProps: MapProperty<String, String>
|
||||
|
||||
fun useMojangMappings() = smcmtkProjectPlugin.configureMojangMappings()
|
||||
fun createModConfigurations(sourceSets: List<SourceSet>) = smcmtkProjectPlugin.createModConfigurations(sourceSets)
|
||||
|
||||
fun useAccessWidener(file: RegularFile) = smcmtkProjectPlugin.configureAccessWidener(file)
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package de.siphalor.minecraft_modding_toolkit.gradle.project_plugin
|
||||
|
||||
import de.siphalor.minecraft_modding_toolkit.gradle.project_plugin.util.joinCamelCase
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.VersionCatalogsExtension
|
||||
import org.gradle.api.file.ProjectLayout
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.provider.ProviderFactory
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.language.jvm.tasks.ProcessResources
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class SmcmtkProjectPlugin : Plugin<Project> {
|
||||
companion object {
|
||||
private const val LOOM_PLAIN_PLUGIN_ID = "net.fabricmc.fabric-loom"
|
||||
private const val LOOM_REMAP_PLUGIN_ID = "net.fabricmc.fabric-loom-remap"
|
||||
|
||||
private val MOD_BASE_CONFIGURATION_NAMES = arrayOf("api", "implementation", "compileOnly", "runtimeOnly", "localRuntime")
|
||||
|
||||
private val ACCESS_WIDENER_DECLARATION_PATTERN = Regex("^accessWidener\\s+v\\d+\\s+")
|
||||
}
|
||||
|
||||
@get:Inject
|
||||
protected abstract val providers: ProviderFactory
|
||||
|
||||
@get:Inject
|
||||
protected abstract val projectLayout: ProjectLayout
|
||||
|
||||
private val logger = lazy { Logging.getLogger(javaClass) }
|
||||
|
||||
private lateinit var project: Project
|
||||
private lateinit var extension: SmcmtkProjectExtension
|
||||
|
||||
private var loomProxy = lazy { project.extensions.findByName("loom")?.let { SmcmtkLoomProxy(project, it)} }
|
||||
|
||||
override fun apply(project: Project) {
|
||||
this.project = project
|
||||
this.extension = project.extensions.create("smcmtk", SmcmtkProjectExtension::class.java, this)
|
||||
|
||||
val minecraftVersionDescriptor = providers.gradleProperty("minecraft.version.descriptor")
|
||||
val minecraftProperties = minecraftVersionDescriptor
|
||||
.flatMap { providers.fileContents(projectLayout.settingsDirectory.file("gradle/mc-$it/gradle.properties")).asBytes }
|
||||
.map { Properties().apply { load(it.inputStream())} }
|
||||
|
||||
extension.mcProps.convention(minecraftProperties.map { mapOf(*it.entries.map { entry -> entry.key.toString() to entry.value.toString() }.toTypedArray()) })
|
||||
|
||||
project.plugins.withId(LOOM_PLAIN_PLUGIN_ID) {
|
||||
project.configurations.maybeCreate("namedElements")
|
||||
.extendsFrom(project.configurations.getByName("apiElements"))
|
||||
}
|
||||
}
|
||||
|
||||
fun configureMojangMappings() {
|
||||
project.plugins.withId(LOOM_REMAP_PLUGIN_ID) {
|
||||
val versionCatalogs = project.extensions.getByType(VersionCatalogsExtension::class.java)
|
||||
val mcLibsCatalog = versionCatalogs.find("mcLibs").orElse(null)
|
||||
val parchment = mcLibsCatalog?.findLibrary("parchment")?.orElse(null)
|
||||
|
||||
loomProxy.value?.configureOfficialMojangMappings(parchment)
|
||||
}
|
||||
project.plugins.withId(LOOM_PLAIN_PLUGIN_ID) {
|
||||
project.tasks.withType(ProcessResources::class.java).findByName("processResources")?.apply {
|
||||
filesMatching("*.accesswidener") {
|
||||
it.filter { line ->
|
||||
if (line.startsWith("accessWidener")) {
|
||||
line.replace("named", "official")
|
||||
} else {
|
||||
line
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createModConfigurations(sourceSets: Collection<SourceSet>) {
|
||||
project.plugins.withId(LOOM_REMAP_PLUGIN_ID) {
|
||||
sourceSets.filter { it.name != "main" }
|
||||
.forEach { sourceSet -> loomProxy.value?.createRemapConfiguration(sourceSet) }
|
||||
}
|
||||
project.plugins.withId(LOOM_PLAIN_PLUGIN_ID) {
|
||||
sourceSets.forEach { sourceSet ->
|
||||
val prefix = if (sourceSet.name == "main") "" else sourceSet.name
|
||||
|
||||
MOD_BASE_CONFIGURATION_NAMES.forEach { baseConfigurationName ->
|
||||
val configurationName = joinCamelCase(prefix, baseConfigurationName)
|
||||
project.configurations.findByName(configurationName)?.let { baseConfiguration ->
|
||||
val configuration = project.configurations
|
||||
.maybeCreate(joinCamelCase("mod", configurationName))
|
||||
baseConfiguration.extendsFrom(configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun configureAccessWidener(file: RegularFile) {
|
||||
logger.value.debug("Configuring access widener {}", file)
|
||||
if (!file.asFile.isFile) {
|
||||
logger.value.debug("Skipping access widener configuration for non-existing file {}", file)
|
||||
return
|
||||
}
|
||||
|
||||
val accessWidenerNamesType = if (project.plugins.hasPlugin(LOOM_PLAIN_PLUGIN_ID)) {
|
||||
"official"
|
||||
} else if (project.plugins.hasPlugin(LOOM_REMAP_PLUGIN_ID)) {
|
||||
"named"
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
if (accessWidenerNamesType != null) {
|
||||
logger.value.info("Changing access widener names type of $file to $accessWidenerNamesType")
|
||||
file.asFile.writeText(file.asFile.readText(Charsets.UTF_8).lines().joinToString("\n") { line ->
|
||||
ACCESS_WIDENER_DECLARATION_PATTERN.matchAt(line, 0)
|
||||
?.let { match -> line.substring(match.range) + accessWidenerNamesType }
|
||||
?: line
|
||||
})
|
||||
} else {
|
||||
logger.value.warn("Could not determine access widener names type for $file")
|
||||
}
|
||||
|
||||
loomProxy.value?.setAccessWidenerPath(file)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package de.siphalor.minecraft_modding_toolkit.gradle.project_plugin.filter
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import java.io.FilterReader
|
||||
import java.io.Reader
|
||||
import java.io.StringReader
|
||||
import java.nio.CharBuffer
|
||||
|
||||
class JsonMergeFilterReader(input: Reader) : FilterReader(input) {
|
||||
companion object {
|
||||
val GSON: Gson = GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create()
|
||||
}
|
||||
|
||||
var merge: MutableMap<String, Any?> = LinkedHashMap()
|
||||
|
||||
val result = lazy {
|
||||
val inputJson = GSON.fromJson(input, Any::class.java)
|
||||
StringReader(GSON.toJson(update(inputJson, merge)))
|
||||
}
|
||||
|
||||
private fun update(input: Any?, update: Any?): Any? {
|
||||
return if (input is Collection<*> && update is Collection<*>) {
|
||||
ArrayList(input).apply { addAll(update) }
|
||||
} else if (input is Map<*, *> && update is Map<*, *>) {
|
||||
LinkedHashMap(input).apply {
|
||||
update.forEach { (key, value) -> put(key, update(input[key], value)) }
|
||||
}
|
||||
} else {
|
||||
update
|
||||
}
|
||||
}
|
||||
|
||||
override fun read(): Int {
|
||||
return result.value.read()
|
||||
}
|
||||
|
||||
override fun read(cbuf: CharArray?): Int {
|
||||
return result.value.read(cbuf)
|
||||
}
|
||||
|
||||
override fun read(cbuf: CharArray?, off: Int, len: Int): Int {
|
||||
return result.value.read(cbuf, off, len)
|
||||
}
|
||||
|
||||
override fun read(target: CharBuffer): Int {
|
||||
return result.value.read(target)
|
||||
}
|
||||
|
||||
override fun skip(n: Long): Long {
|
||||
return result.value.skip(n)
|
||||
}
|
||||
|
||||
override fun ready(): Boolean {
|
||||
return result.value.ready()
|
||||
}
|
||||
|
||||
override fun markSupported(): Boolean {
|
||||
return result.value.markSupported()
|
||||
}
|
||||
|
||||
override fun mark(readAheadLimit: Int) {
|
||||
result.value.mark(readAheadLimit)
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
result.value.reset()
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
result.value.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.siphalor.minecraft_modding_toolkit.gradle.project_plugin.util
|
||||
|
||||
fun joinCamelCase(vararg words: String) = words
|
||||
.joinToString("") { word -> word.replaceFirstChar { if (it.isLowerCase()) it.uppercaseChar() else it } }
|
||||
.replaceFirstChar { it.lowercaseChar() }
|
||||
|
||||
Reference in New Issue
Block a user