Skip to content

Commit 897066f

Browse files
committed
Require manual project-graph configuration and add support for Fabric
1 parent 8e84806 commit 897066f

File tree

5 files changed

+235
-80
lines changed

5 files changed

+235
-80
lines changed

build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ repositories {
4141
mavenLocal()
4242
mavenCentral()
4343
maven(url = "https://jitpack.io")
44+
maven(url = "https://maven.fabricmc.net")
4445
}
4546

4647
dependencies {
4748
implementation(gradleApi())
4849
compile(localGroovy())
49-
implementation("com.github.replaymod:remap:fb0e54a")
50+
implementation("com.github.replaymod:remap:64d841a")
51+
implementation("net.fabricmc:tiny-mappings-parser:0.1.1.8")
5052
}
Lines changed: 99 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.replaymod.gradle.preprocess
22

3+
import net.fabricmc.mappings.MappingsProvider
4+
import org.cadixdev.lorenz.io.MappingFormats
35
import org.gradle.api.Plugin
46
import org.gradle.api.Project
57
import org.gradle.api.Task
@@ -10,22 +12,28 @@ import org.gradle.api.tasks.compile.AbstractCompile
1012

1113
import org.gradle.kotlin.dsl.*
1214
import java.io.File
13-
import java.util.*
1415

1516
class PreprocessPlugin : Plugin<Project> {
1617
override fun apply(project: Project) {
17-
val kotlin = project.plugins.hasPlugin("kotlin")
18+
val parent = project.parent
19+
if (parent == null) {
20+
project.extensions.create("preprocess", RootPreprocessExtension::class)
21+
return
22+
}
1823

19-
val coreVersionFile = project.file("../mainVersion")
20-
val mappingFiles = findMappingFiles(project)
24+
val rootExtension = parent.extensions.getByType<RootPreprocessExtension>()
25+
val graph = rootExtension.rootNode ?: throw IllegalStateException("Preprocess graph was not configured.")
26+
val projectNode = graph.findNode(project.name) ?: throw IllegalStateException("Prepocess graph does not contain ${project.name}.")
2127

22-
val parent = project.parent!!
23-
val coreVersion = coreVersionFile.readText().toInt()
24-
val mcVersion = project.getMcVersion()
28+
val coreProjectFile = project.file("../mainProject")
29+
val coreProject = coreProjectFile.readText().trim()
30+
val mcVersion = projectNode.mcVersion
2531
project.extra["mcVersion"] = mcVersion
2632
val ext = project.extensions.create("preprocess", PreprocessExtension::class, project.objects, mcVersion)
2733

28-
if (coreVersion == mcVersion) {
34+
val kotlin = project.plugins.hasPlugin("kotlin")
35+
36+
if (coreProject == project.name) {
2937
project.the<SourceSetContainer>().configureEach {
3038
java.setSrcDirs(listOf(parent.file("src/$name/java")))
3139
resources.setSrcDirs(listOf(parent.file("src/$name/resources")))
@@ -37,37 +45,10 @@ class PreprocessPlugin : Plugin<Project> {
3745
}
3846
}
3947
} else {
40-
val core = project.byVersion(coreVersion)
41-
val mappingFile: File?
42-
val inherited: Project?
43-
if (coreVersion < mcVersion) {
44-
// Upgrading older core to newer version
45-
// Grab the next mapping at or below our version
46-
// e.g. if we're on 1.13.2, that'll be 11302 which maps 1.13.2 to 1.12.2
47-
val entry = mappingFiles.floorEntry(mcVersion)
48-
if (entry == null || entry.key <= coreVersion) {
49-
inherited = core
50-
mappingFile = null
51-
} else {
52-
mappingFile = entry.value
53-
// Inherit from the version directly below the mapping we"re using
54-
val inheritedVersion = mappingFiles.lowerKey(entry.key)
55-
inherited = inheritedVersion?.let { project.byVersion(it) } ?: core
56-
}
57-
} else {
58-
// Dowgrading newer core to older versions
59-
// Grab the next mapping on our way to the newer core version (i.e. the one right above our version)
60-
val entry = mappingFiles.higherEntry(mcVersion)
61-
if (entry == null || entry.key > coreVersion) {
62-
inherited = core
63-
mappingFile = null
64-
} else {
65-
mappingFile = entry.value
66-
// Inherit from the version which the mapping belongs to
67-
// e.g. if we're on 1.12.2 then the mapping maps 1.13.2 to 1.12.2 and will be labeled 11302
68-
inherited = project.byVersion(entry.key)
69-
}
70-
}
48+
val inheritedLink = projectNode.links.find { it.first.findNode(coreProject) != null }
49+
val reverseMappings = inheritedLink != null
50+
val (inheritedNode, mappingFile) = inheritedLink ?: graph.findParent(projectNode)!!
51+
val inherited = parent.evaluationDependsOn(inheritedNode.project)
7152

7253
project.the<SourceSetContainer>().configureEach {
7354
val inheritedSourceSet = inherited.the<SourceSetContainer>()[name]
@@ -84,7 +65,7 @@ class PreprocessPlugin : Plugin<Project> {
8465
compileTask(inherited.tasks["compile${cName}Kotlin"] as AbstractCompile)
8566
}
8667
mapping = mappingFile
87-
reverseMapping = coreVersion < mcVersion
68+
reverseMapping = reverseMappings
8869
vars.convention(ext.vars)
8970
keywords.convention(ext.keywords)
9071
}
@@ -98,7 +79,7 @@ class PreprocessPlugin : Plugin<Project> {
9879
generated = preprocessedKotlin
9980
compileTask(inherited.tasks["compile${cName}Kotlin"] as AbstractCompile)
10081
mapping = mappingFile
101-
reverseMapping = coreVersion < mcVersion
82+
reverseMapping = reverseMappings
10283
vars.convention(ext.vars)
10384
keywords.convention(ext.keywords)
10485
}
@@ -120,14 +101,32 @@ class PreprocessPlugin : Plugin<Project> {
120101
}
121102

122103
project.afterEvaluate {
104+
val prepareTaskName = "prepareMappingsForPreprocessor"
123105
val projectIntermediaryMappings = project.intermediaryMappings
124106
val inheritedIntermediaryMappings = inherited.intermediaryMappings
125-
if (inheritedIntermediaryMappings != null && projectIntermediaryMappings != null) {
126-
tasks.withType<PreprocessTask>().configureEach {
127-
sourceMappings = inheritedIntermediaryMappings.first
128-
destinationMappings = projectIntermediaryMappings.first
129-
(inheritedIntermediaryMappings.second + projectIntermediaryMappings.second).forEach { dependsOn(it) }
107+
val projectNotchMappings = project.notchMappings
108+
val inheritedNotchMappings = inherited.notchMappings
109+
val sourceSrg = project.buildDir.resolve(prepareTaskName).resolve("source.srg")
110+
val destinationSrg = project.buildDir.resolve(prepareTaskName).resolve("destination.srg")
111+
val prepareTask = if (inheritedIntermediaryMappings != null && projectIntermediaryMappings != null
112+
&& inheritedIntermediaryMappings.type == projectIntermediaryMappings.type) {
113+
tasks.register(prepareTaskName) {
114+
bakeNamedToIntermediaryMappings(inheritedIntermediaryMappings, sourceSrg)
115+
bakeNamedToIntermediaryMappings(projectIntermediaryMappings, destinationSrg)
116+
}
117+
} else if (inheritedNotchMappings != null && projectNotchMappings != null
118+
&& inheritedNode.mcVersion == projectNode.mcVersion) {
119+
tasks.register(prepareTaskName) {
120+
bakeNamedToOfficialMappings(inheritedNotchMappings, inheritedIntermediaryMappings, sourceSrg)
121+
bakeNamedToOfficialMappings(projectNotchMappings, projectIntermediaryMappings, destinationSrg)
130122
}
123+
} else {
124+
throw IllegalStateException("Failed to find mappings from $inherited to $project.")
125+
}
126+
tasks.withType<PreprocessTask>().configureEach {
127+
sourceMappings = sourceSrg
128+
destinationMappings = destinationSrg
129+
dependsOn(prepareTask)
131130
}
132131
}
133132

@@ -146,42 +145,74 @@ class PreprocessPlugin : Plugin<Project> {
146145
}
147146

148147
doLast {
149-
coreVersionFile.writeText(mcVersion.toString())
148+
coreProjectFile.writeText(project.name)
150149
}
151150
}
152151
}
153152
}
154153
}
155154

156-
private fun Project.getMcVersion(): Int = (name.split(".") + listOf("")).let { (major, minor, patch) ->
157-
"$major${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt()
155+
private fun Task.bakeNamedToIntermediaryMappings(mappings: Mappings, destination: File) {
156+
mappings.tasks.forEach { this.dependsOn(it) }
157+
inputs.file(mappings.file)
158+
outputs.file(destination)
159+
doLast {
160+
val mapping = if (mappings.format == "tiny") {
161+
val tiny = mappings.file.inputStream().use { MappingsProvider.readTinyMappings(it) }
162+
TinyReader(tiny, "named", "intermediary", false).read()
163+
} else {
164+
MappingFormats.byId(mappings.format).read(mappings.file.toPath())
165+
}
166+
MappingFormats.SRG.write(mapping, destination.toPath())
167+
}
158168
}
159169

160-
private fun Project.byVersion(version: Int): Project {
161-
val name = "${version/10000}.${version/100 % 100}${if (version%100 == 0) "" else ".${version%100}"}"
162-
return project.parent!!.evaluationDependsOn(name)
170+
private fun Task.bakeNamedToOfficialMappings(mappings: Mappings, namedToIntermediaryMappings: Mappings?, destination: File) {
171+
mappings.tasks.forEach { this.dependsOn(it) }
172+
namedToIntermediaryMappings?.tasks?.forEach { dependsOn(it) }
173+
inputs.file(mappings.file)
174+
namedToIntermediaryMappings?.let { inputs.file(it.file) }
175+
outputs.file(destination)
176+
doLast {
177+
val mapping = if (mappings.format == "tiny") {
178+
val tiny = mappings.file.inputStream().use { MappingsProvider.readTinyMappings(it) }
179+
TinyReader(tiny, "named", "official", false).read()
180+
} else {
181+
val iMappings = namedToIntermediaryMappings!!
182+
val iMapSet = MappingFormats.byId(iMappings.format).read(iMappings.file.toPath())
183+
val oMapSet = MappingFormats.byId(mappings.format).read(mappings.file.toPath())
184+
oMapSet.join(iMapSet.reverse()).reverse()
185+
}
186+
MappingFormats.SRG.write(mapping, destination.toPath())
187+
}
163188
}
164189

165-
private fun findMappingFiles(project: Project): NavigableMap<Int, File> =
166-
project.file("../").listFiles()!!.mapNotNull {
167-
val mappingFile = File(it, "mapping.txt")
168-
if (mappingFile.exists()) {
169-
val (major, minor, patch) = it.name.split(".") + listOf(null)
170-
val version = "$major${minor?.padStart(2, '0')}${(patch ?: "").padStart(2, '0')}"
171-
Pair(version.toInt(), mappingFile)
172-
} else {
173-
null
174-
}
175-
}.toMap(TreeMap())
176-
177-
178-
private val Project.intermediaryMappings: Pair<File, List<Task>>?
190+
private val Project.intermediaryMappings: Mappings?
179191
get() {
180192
project.tasks.findByName("genSrgs")?.let { // FG2
181-
return Pair(it.property("mcpToSrg") as File, listOf(it))
193+
return Mappings("searge", it.property("mcpToSrg") as File, "srg", listOf(it))
182194
}
183195
project.tasks.findByName("createMcpToSrg")?.let { // FG3
184-
return Pair(it.property("output") as File, listOf(it))
196+
return Mappings("searge", it.property("output") as File, "tsrg", listOf(it))
185197
}
198+
tinyMappings?.let { return Mappings("yarn", it, "tiny", emptyList()) }
186199
return null
187200
}
201+
202+
data class Mappings(val type: String, val file: File, val format: String, val tasks: List<Task>)
203+
204+
private val Project.notchMappings: Mappings?
205+
get() {
206+
project.tasks.findByName("extractSrg")?.let { // FG3
207+
return Mappings("notch", it.property("output") as File, "tsrg", listOf(it))
208+
}
209+
tinyMappings?.let { return Mappings("notch", it, "tiny", emptyList()) }
210+
return null
211+
}
212+
213+
private val Project.tinyMappings: File?
214+
get() {
215+
val extension = extensions.findByName("minecraft") ?: return null
216+
if (!extension.javaClass.name.contains("LoomGradleExtension")) return null
217+
return extension.withGroovyBuilder { getProperty("mappingsProvider") }.withGroovyBuilder { getProperty("MAPPINGS_TINY") } as File
218+
}

src/main/kotlin/com/replaymod/gradle/preprocess/PreprocessTask.kt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.replaymod.gradle.remap.Transformer
44
import com.replaymod.gradle.remap.legacy.LegacyMapping
55
import com.replaymod.gradle.remap.legacy.LegacyMappingSetModelFactory
66
import org.cadixdev.lorenz.MappingSet
7+
import org.cadixdev.lorenz.io.MappingFormats
78
import org.gradle.api.DefaultTask
89
import org.gradle.api.file.FileCollection
910
import org.gradle.api.tasks.*
@@ -107,20 +108,27 @@ open class PreprocessTask : DefaultTask() {
107108

108109
val mapping = mapping
109110
val classpath = classpath
110-
if (mapping != null && classpath != null) {
111-
val mappings = if (sourceMappings?.exists() == true && destinationMappings?.exists() == true) {
112-
val legacyMap = LegacyMapping.readMappingSet(mapping.toPath(), reverseMapping)
113-
val clsMap = legacyMap.splitOffClassMappings()
111+
if (classpath != null && (mapping != null || sourceMappings != null && destinationMappings != null)) {
112+
val mappings = if (mapping != null) {
113+
if (sourceMappings != null && destinationMappings != null) {
114+
val legacyMap = LegacyMapping.readMappingSet(mapping.toPath(), reverseMapping)
115+
val clsMap = legacyMap.splitOffClassMappings()
116+
val srcMap = sourceMappings!!.readMappings()
117+
val dstMap = destinationMappings!!.readMappings()
118+
legacyMap.mergeBoth(
119+
// The inner clsMap is to make the join work, the outer one for custom classes (which are not part of
120+
// dstMap and would otherwise be filtered by the join)
121+
srcMap.mergeBoth(clsMap).join(dstMap.reverse()).mergeBoth(clsMap),
122+
MappingSet.create(LegacyMappingSetModelFactory()))
123+
} else {
124+
LegacyMapping.readMappingSet(mapping.toPath(), reverseMapping)
125+
}
126+
} else {
114127
val srcMap = sourceMappings!!.readMappings()
115128
val dstMap = destinationMappings!!.readMappings()
116-
legacyMap.mergeBoth(
117-
// The inner clsMap is to make the join work, the outer one for custom classes (which are not part of
118-
// dstMap and would otherwise be filtered by the join)
119-
srcMap.mergeBoth(clsMap).join(dstMap.reverse()).mergeBoth(clsMap),
120-
MappingSet.create(LegacyMappingSetModelFactory()))
121-
} else {
122-
LegacyMapping.readMappingSet(mapping.toPath(), reverseMapping)
129+
srcMap.join(dstMap.reverse())
123130
}
131+
MappingFormats.SRG.write(mappings, project.file("tmp.srg").toPath())
124132
val javaTransformer = Transformer(mappings)
125133
LOGGER.debug("Remap Classpath:")
126134
javaTransformer.classpath = classpath.files.mapNotNull {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.replaymod.gradle.preprocess
2+
3+
import java.io.File
4+
5+
open class RootPreprocessExtension : ProjectGraphNodeDSL {
6+
var rootNode: ProjectGraphNode? = null
7+
8+
override fun addNode(project: String, mcVersion: Int, mappings: String, extraMappings: File?): ProjectGraphNode {
9+
check(rootNode == null) { "Only one root node may be set." }
10+
check(extraMappings == null) { "Cannot add extra mappings to root node." }
11+
return ProjectGraphNode(project, mcVersion, mappings).also { rootNode = it }
12+
}
13+
}
14+
15+
interface ProjectGraphNodeDSL {
16+
operator fun String.invoke(mcVersion: Int, mappings: String, extraMappings: File? = null, configure: ProjectGraphNodeDSL.() -> Unit = {}) {
17+
addNode(this, mcVersion, mappings, extraMappings).configure()
18+
}
19+
20+
fun addNode(project: String, mcVersion: Int, mappings: String, extraMappings: File? = null): ProjectGraphNodeDSL
21+
}
22+
23+
open class ProjectGraphNode(
24+
val project: String,
25+
val mcVersion: Int,
26+
val mappings: String,
27+
val links: MutableList<Pair<ProjectGraphNode, File?>> = mutableListOf()
28+
) : ProjectGraphNodeDSL {
29+
override fun addNode(project: String, mcVersion: Int, mappings: String, extraMappings: File?): ProjectGraphNodeDSL =
30+
ProjectGraphNode(project, mcVersion, mappings).also { links.add(Pair(it, extraMappings)) }
31+
32+
fun findNode(project: String): ProjectGraphNode? = if (project == this.project) {
33+
this
34+
} else {
35+
links.map { it.first.findNode(project) }.find { it != null }
36+
}
37+
38+
fun findParent(node: ProjectGraphNode): Pair<ProjectGraphNode, File?>? = if (node == this) {
39+
null
40+
} else {
41+
links.map { (child, extraMappings) ->
42+
if (child == node) {
43+
Pair(this, extraMappings)
44+
} else {
45+
child.findParent(node)
46+
}
47+
}.find { it != null }
48+
}
49+
}

0 commit comments

Comments
 (0)