]> git.lizzy.rs Git - LightOverlay.git/blob - architectPlugin/src/main/kotlin/me/shedaniel/plugin/architect/RemapMCPTask.kt
We need an extra line here
[LightOverlay.git] / architectPlugin / src / main / kotlin / me / shedaniel / plugin / architect / RemapMCPTask.kt
1 @file:Suppress("UnstableApiUsage")
2
3 package me.shedaniel.plugin.architect
4
5 import net.fabricmc.loom.LoomGradleExtension
6 import net.fabricmc.loom.util.GradleSupport
7 import net.fabricmc.loom.util.TinyRemapperMappingsHelper
8 import net.fabricmc.mapping.tree.TinyTree
9 import net.fabricmc.tinyremapper.IMappingProvider
10 import net.fabricmc.tinyremapper.NonClassCopyMode
11 import net.fabricmc.tinyremapper.OutputConsumerPath
12 import net.fabricmc.tinyremapper.TinyRemapper
13 import org.gradle.api.file.RegularFileProperty
14 import org.gradle.api.tasks.TaskAction
15 import org.gradle.jvm.tasks.Jar
16 import java.io.FileNotFoundException
17 import java.io.InputStream
18 import java.net.URL
19 import java.nio.file.Files
20 import java.nio.file.Path
21
22
23 open class RemapMCPTask : Jar() {
24     private val fromM: String = "named"
25     private val toM: String = "official"
26     val input: RegularFileProperty = GradleSupport.getfileProperty(project)
27
28     @TaskAction
29     fun doTask() {
30         val input: Path = this.input.asFile.get().toPath()
31         val output: Path = this.archiveFile.get().asFile.toPath()
32
33         output.toFile().delete()
34
35         if (!Files.exists(input)) {
36             throw FileNotFoundException(input.toString())
37         }
38
39         val remapperBuilder: TinyRemapper.Builder = TinyRemapper.newRemapper()
40         val mappings = getMappings()
41         val mojmapToMcpClass = createMojmapToMcpClass(mappings)
42         remapperBuilder.withMappings(remapToMcp(TinyRemapperMappingsHelper.create(mappings, fromM, toM, false), mojmapToMcpClass))
43
44         project.logger.lifecycle(":remapping " + input.fileName)
45
46         val architectFolder = project.rootProject.buildDir.resolve("tmp/architect")
47         architectFolder.deleteRecursively()
48         architectFolder.mkdirs()
49         val manifestFile = architectFolder.resolve("META-INF/MANIFEST.MF")
50         manifestFile.parentFile.mkdirs()
51         manifestFile.writeText("""
52 Manifest-Version: 1.0
53 FMLModType: LIBRARY
54
55         """.trimIndent())
56
57         val remapper = remapperBuilder.build()
58
59         try {
60             OutputConsumerPath.Builder(output).build().use { outputConsumer ->
61                 outputConsumer.addNonClassFiles(input, NonClassCopyMode.SKIP_META_INF, null)
62                 outputConsumer.addNonClassFiles(architectFolder.toPath(), NonClassCopyMode.UNCHANGED, null)
63                 remapper.readInputs(input)
64                 remapper.apply(outputConsumer)
65             }
66         } catch (e: Exception) {
67             remapper.finish()
68             throw RuntimeException("Failed to remap $input to $output", e)
69         }
70
71         architectFolder.deleteRecursively()
72         remapper.finish()
73
74         if (!Files.exists(output)) {
75             throw RuntimeException("Failed to remap $input to $output - file missing!")
76         }
77     }
78
79     private fun remapToMcp(parent: IMappingProvider, mojmapToMcpClass: Map<String, String>): IMappingProvider = IMappingProvider {
80         it.acceptClass("net/fabricmc/api/Environment","net/minecraftforge/api/distmarker/OnlyIn") 
81         it.acceptClass("net/fabricmc/api/EnvType","net/minecraftforge/api/distmarker/Dist") 
82         it.acceptField(IMappingProvider.Member("net/fabricmc/api/EnvType", "SERVER", "Lnet/fabricmc/api/EnvType;"),"DEDICATED_SERVER") 
83         
84         parent.load(object : IMappingProvider.MappingAcceptor {
85             override fun acceptClass(srcName: String?, dstName: String?) {
86                 it.acceptClass(srcName, mojmapToMcpClass[srcName] ?: srcName)
87             }
88
89             override fun acceptMethod(method: IMappingProvider.Member?, dstName: String?) {
90                 it.acceptMethod(method, dstName)
91             }
92
93             override fun acceptMethodArg(method: IMappingProvider.Member?, lvIndex: Int, dstName: String?) {
94                 it.acceptMethodArg(method, lvIndex, dstName)
95             }
96
97             override fun acceptMethodVar(method: IMappingProvider.Member?, lvIndex: Int, startOpIdx: Int, asmIndex: Int, dstName: String?) {
98                 it.acceptMethodVar(method, lvIndex, startOpIdx, asmIndex, dstName)
99             }
100
101             override fun acceptField(field: IMappingProvider.Member?, dstName: String?) {
102                 it.acceptField(field, dstName)
103             }
104         })
105     }
106
107     private fun getMappings(): TinyTree {
108         val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java)
109         return loomExtension.mappingsProvider.mappings
110     }
111
112     private fun getRootExtension(): ArchitectPluginExtension =
113             project.rootProject.extensions.getByType(ArchitectPluginExtension::class.java)
114
115     private fun createMojmapToMcpClass(mappings: TinyTree): Map<String, String> {
116         val mcpMappings = readMCPMappings(getRootExtension().minecraft)
117         val mutableMap = mutableMapOf<String, String>()
118         mappings.classes.forEach { clazz ->
119             val official = clazz.getName("official")
120             val named = clazz.getName("named")
121             val mcp = mcpMappings[official]
122             if (mcp != null) {
123                 mutableMap[named] = mcp
124             }
125         }
126         return mutableMap
127     }
128
129     private fun readMCPMappings(version: String): Map<String, String> {
130         val file = project.rootProject.file(".gradle/mappings/mcp-$version.tsrg")
131         if (file.exists().not()) {
132             file.parentFile.mkdirs()
133             file.writeText(URL("https://raw.githubusercontent.com/MinecraftForge/MCPConfig/master/versions/release/$version/joined.tsrg").readText())
134         }
135         return mutableMapOf<String, String>().also { readMappings(it, file.inputStream()) }
136     }
137
138     private fun readMappings(mutableMap: MutableMap<String, String>, inputStream: InputStream) {
139         inputStream.bufferedReader().forEachLine {
140             if (!it.startsWith("\t")) {
141                 val split = it.split(" ")
142                 val obf = split[0]
143                 val className = split[1]
144                 mutableMap[obf] = className
145             }
146         }
147     }
148 }