Remove old unused tasks, add the remap of mixins for the common modules

This commit is contained in:
shedaniel
2020-12-30 18:52:48 +08:00
parent 30a37abdc5
commit b1a5022c8c
5 changed files with 182 additions and 58 deletions

View File

@@ -28,14 +28,16 @@ dependencies {
implementation gradleApi()
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72"
implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.72"
implementation "me.shedaniel:forgified-fabric-loom:0.5.12"
runtime "me.shedaniel:forgified-fabric-loom:0.5.12"
implementation "me.shedaniel:forgified-fabric-loom:$loom_version"
runtime "me.shedaniel:forgified-fabric-loom:$loom_version"
implementation "net.fabricmc:tiny-remapper:0.3.0.70"
implementation "net.fabricmc:tiny-mappings-parser:0.2.2.14"
implementation "org.ow2.asm:asm:8.0"
implementation "org.ow2.asm:asm-commons:8.0"
implementation "org.ow2.asm:asm-tree:8.0"
implementation "org.ow2.asm:asm-util:8.0"
implementation "org.zeroturnaround:zt-zip:1.13"
implementation "com.google.code.gson:gson:2.8.5"
}
compileKotlin {

View File

@@ -1 +1,2 @@
kotlin.code.style=official
kotlin.code.style=official
loom_version=0.5.16

View File

@@ -29,16 +29,8 @@ class ArchitectPlugin : Plugin<Project> {
}
}
project.tasks.register("remapMcp", RemapMCPTask::class.java) {
it.group = "Architect"
}
project.tasks.register("remapMcpFakeMod", RemapMCPTask::class.java) {
it.fakeMod = true
it.group = "Architect"
}
project.tasks.register("transformForge", RemapMCPTask::class.java) {
it.fakeMod = false
it.remapMcp = false
it.group = "Architect"
}

View File

@@ -57,31 +57,11 @@ open class ArchitectPluginExtension(val project: Project) {
} as RemapJarTask
if (forgeEnabled) {
val remapMCPTask = project.tasks.getByName("remapMcp") {
it as RemapMCPTask
it.input.set(transformArchitectJarTask.archiveFile.get())
it.archiveClassifier.set("mcp")
it.dependsOn(transformArchitectJarTask)
buildTask.dependsOn(it)
it.outputs.upToDateWhen { false }
} as RemapMCPTask
val remapMCPFakeModTask = project.tasks.getByName("remapMcpFakeMod") {
it as RemapMCPTask
it.input.set(transformArchitectJarTask.archiveFile.get())
it.archiveClassifier.set("mcpGenerateMod")
it.dependsOn(transformArchitectJarTask)
buildTask.dependsOn(it)
it.outputs.upToDateWhen { false }
} as RemapMCPTask
val transformForgeTask = project.tasks.getByName("transformForge") {
it as RemapMCPTask
it.input.set(transformArchitectJarTask.archiveFile.get())
it.archiveClassifier.set("transformForge")
it.archiveClassifier.set("transformedForge")
it.dependsOn(transformArchitectJarTask)
buildTask.dependsOn(it)
it.outputs.upToDateWhen { false }
@@ -91,27 +71,13 @@ open class ArchitectPluginExtension(val project: Project) {
it as RemapMCPTask
it.input.set(transformArchitectJarTask.archiveFile.get())
it.archiveClassifier.set("transformForgeFakeMod")
it.archiveClassifier.set("transformedForgeFakeMod")
it.dependsOn(transformArchitectJarTask)
buildTask.dependsOn(it)
it.outputs.upToDateWhen { false }
} as RemapMCPTask
project.artifacts {
it.add(
"mcp", mapOf(
"file" to remapMCPTask.archiveFile.get().asFile,
"type" to "jar",
"builtBy" to remapMCPTask
)
)
it.add(
"mcpGenerateMod", mapOf(
"file" to remapMCPFakeModTask.archiveFile.get().asFile,
"type" to "jar",
"builtBy" to remapMCPFakeModTask
)
)
it.add(
"transformForge", mapOf(
"file" to transformForgeTask.archiveFile.get().asFile,
@@ -127,6 +93,8 @@ open class ArchitectPluginExtension(val project: Project) {
)
)
}
project.extensions.getByType(LoomGradleExtension::class.java).generateSrgTiny = true
}
project.artifacts {

View File

@@ -2,6 +2,9 @@
package me.shedaniel.architect.plugin
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import me.shedaniel.architect.plugin.utils.GradleSupport
import net.fabricmc.loom.LoomGradleExtension
import net.fabricmc.loom.util.LoggerFilter
@@ -20,13 +23,14 @@ import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.AnnotationNode
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodInsnNode
import java.io.File
import java.io.FileNotFoundException
import java.io.InputStream
import org.zeroturnaround.zip.ByteSource
import org.zeroturnaround.zip.ZipUtil
import java.io.*
import java.net.URL
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
import java.util.jar.Manifest
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
@@ -34,7 +38,6 @@ import kotlin.collections.LinkedHashSet
open class RemapMCPTask : Jar() {
private val fromM: String = "named"
private val toM: String = "official"
var remapMcp = true
var fakeMod = false
val input: RegularFileProperty = GradleSupport.getFileProperty(project)
@@ -102,7 +105,14 @@ open class RemapMCPTask : Jar() {
remapperBuilder.skipLocalVariableMapping(true)
}
project.logger.lifecycle(":remapping " + input.fileName)
project.logger.lifecycle(
":${
listOfNotNull(
"remapping".takeIf { remapMcp },
"transforming"
).joinToString(" and ")
} " + input.fileName + " => " + output.fileName + if (fakeMod) " (with fake mod)" else ""
)
val architectFolder = project.rootProject.buildDir.resolve("tmp/architect")
architectFolder.deleteRecursively()
@@ -133,7 +143,7 @@ modId = "$fakeModId"
try {
OutputConsumerPath.Builder(output).build().use { outputConsumer ->
outputConsumer.addNonClassFiles(input, NonClassCopyMode.SKIP_META_INF, null)
outputConsumer.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, null)
outputConsumer.addNonClassFiles(architectFolder.toPath(), NonClassCopyMode.UNCHANGED, null)
remapper.readClassPath(*classpath)
remapper.readInputs(intermediate)
@@ -165,13 +175,164 @@ modId = "$fakeModId"
architectFolder.deleteRecursively()
remapper.finish()
// intermediate.toFile().delete()
intermediate.toFile().delete()
fixMixins(output.toFile())
if (!Files.exists(output)) {
throw RuntimeException("Failed to remap $input to $output - file missing!")
}
}
private fun fixMixins(output: File) {
val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java)
val gson = GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create()
val mixinConfigs = mutableMapOf<String, JsonObject>()
val refmap = loomExtension.getRefmapName()
ZipUtil.iterate(output) { stream, entry ->
if (!entry.isDirectory && entry.name.endsWith(".json") &&
!entry.name.contains("/") && !entry.name.contains("\\")
) {
try {
InputStreamReader(stream).use { reader ->
val json: JsonObject? = gson.fromJson<JsonObject>(reader, JsonObject::class.java)
if (json != null) {
val hasMixins = json.has("mixins") && json["mixins"].isJsonArray
val hasClient = json.has("client") && json["client"].isJsonArray
val hasServer = json.has("server") && json["server"].isJsonArray
if (json.has("package") && (hasMixins || hasClient || hasServer)) {
mixinConfigs[entry.name] = json.deepCopy().also {
it.addProperty("refmap", refmap)
}
}
}
}
} catch (ignored: Exception) {
}
}
}
ZipUtil.replaceEntries(output, mixinConfigs.entries.map { (path, obj) ->
ByteSource(path, gson.toJson(obj).toByteArray())
}.toTypedArray())
if (mixinConfigs.isNotEmpty()) {
if (ZipUtil.containsEntry(output, "META-INF/MANIFEST.MF")) {
ZipUtil.transformEntry(output, "META-INF/MANIFEST.MF") { input, zipEntry, out ->
val manifest = Manifest(input)
manifest.mainAttributes.putValue("MixinConfigs", mixinConfigs.keys.joinToString(","))
out.putNextEntry(ZipEntry(zipEntry.name))
manifest.write(out)
out.closeEntry()
}
}
}
ZipUtil.transformEntry(output, refmap) { input, zipEntry, out ->
val refmapElement: JsonObject = JsonParser().parse(InputStreamReader(input)).asJsonObject.deepCopy()
if (refmapElement.has("mappings")) {
refmapElement["mappings"].asJsonObject.entrySet().forEach { (_, value) ->
remapRefmap(value.asJsonObject)
}
}
if (refmapElement.has("data")) {
val data = refmapElement["data"].asJsonObject
if (data.has("named:intermediary")) {
data.add("searge", data["named:intermediary"].deepCopy().also {
it.asJsonObject.entrySet().forEach { (_, value) ->
remapRefmap(value.asJsonObject)
}
})
data.remove("named:intermediary")
}
}
out.putNextEntry(ZipEntry(zipEntry.name))
out.write(gson.toJson(refmapElement).toByteArray())
out.closeEntry()
}
}
private fun remapRefmap(obj: JsonObject) {
val srg = project.extensions.getByType(LoomGradleExtension::class.java).mappingsProvider.mappingsWithSrg
val methodPattern = "L(.*);(.*)(\\(.*)".toRegex()
val fieldPattern = "(.*):(.*)".toRegex()
obj.keySet().forEach { key ->
val originalRef = obj[key].asString
val methodMatch = methodPattern.matchEntire(originalRef)
val fieldMatch = fieldPattern.matchEntire(originalRef)
when {
methodMatch != null -> {
val matchedClass =
srg.classes.firstOrNull { it.getName("intermediary") == methodMatch.groups[1]!!.value }
val replacementName: String = srg.classes.asSequence()
.flatMap { it.methods.asSequence() }
.filter { it.getName("intermediary") == methodMatch.groups[2]!!.value }
.firstOrNull { it.getDescriptor("intermediary") == methodMatch.groups[3]!!.value }
?.getName("srg") ?: methodMatch.groups[2]!!.value
obj.addProperty(
key, originalRef
.replaceFirst(
methodMatch.groups[1]!!.value,
matchedClass?.getName("srg") ?: methodMatch.groups[1]!!.value
)
.replaceFirst(methodMatch.groups[2]!!.value, replacementName)
.replaceFirst(methodMatch.groups[3]!!.value, methodMatch.groups[3]!!.value.remapDescriptor {
srg.classes.firstOrNull { def -> def.getName("intermediary") == it }?.getName("srg")
?: it
})
)
}
fieldMatch != null -> {
val replacementName: String = srg.classes.asSequence()
.flatMap { it.fields.asSequence() }
.filter { it.getName("intermediary") == fieldMatch.groups[1]!!.value }
.firstOrNull { it.getDescriptor("intermediary") == fieldMatch.groups[2]!!.value }
?.getName("srg") ?: fieldMatch.groups[1]!!.value
obj.addProperty(
key, originalRef
.replaceFirst(fieldMatch.groups[1]!!.value, replacementName)
.replaceFirst(fieldMatch.groups[2]!!.value, fieldMatch.groups[2]!!.value.remapDescriptor {
srg.classes.firstOrNull { def -> def.getName("intermediary") == it }?.getName("srg")
?: it
})
)
}
else -> logger.warn("Failed to remap refmap value: $originalRef")
}
}
}
private fun String.remapDescriptor(classMappings: (String) -> String): String {
return try {
val reader = StringReader(this)
val result = StringBuilder()
var insideClassName = false
val className = StringBuilder()
while (true) {
val c: Int = reader.read()
if (c == -1) {
break
}
if (c == ';'.toInt()) {
insideClassName = false
result.append(classMappings(className.toString()))
}
if (insideClassName) {
className.append(c.toChar())
} else {
result.append(c.toChar())
}
if (!insideClassName && c == 'L'.toInt()) {
insideClassName = true
className.setLength(0)
}
}
result.toString()
} catch (e: IOException) {
throw AssertionError(e)
}
}
private fun remapToMcp(parent: IMappingProvider?, mojmapToMcpClass: Map<String, String>?): IMappingProvider =
IMappingProvider { out ->
out.acceptClass("net/fabricmc/api/Environment", "net/minecraftforge/api/distmarker/OnlyIn")
@@ -254,8 +415,8 @@ modId = "$fakeModId"
val cancellable = "Lnet/minecraftforge/eventbus/api/Cancelable;"
private fun transform(node: ClassNode): ClassNode {
if(node.access and Opcodes.ACC_INTERFACE == 0) {
if(node.visibleAnnotations?.any { it.desc == forgeEvent || it.desc == forgeEventCancellable} == true) {
if (node.access and Opcodes.ACC_INTERFACE == 0) {
if (node.visibleAnnotations?.any { it.desc == forgeEvent || it.desc == forgeEventCancellable } == true) {
node.superName = "net/minecraftforge/eventbus/api/Event"
node.methods.forEach {
if (it.name == "<init>") {
@@ -275,7 +436,7 @@ modId = "$fakeModId"
}
// if @ForgeEventCancellable, add the cancellable annotation from forge
node.visibleAnnotations.apply {
if(any {it.desc == forgeEventCancellable}) {
if (any { it.desc == forgeEventCancellable }) {
add(AnnotationNode(cancellable))
}
}