Datagen insanity, dependency, mixin & AW remapping #4
|
@ -7,7 +7,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "dev.frogmc"
|
group = "dev.frogmc"
|
||||||
version = "0.0.1-alpha.15"
|
version = "0.0.1-alpha.16"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
|
@ -24,7 +24,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("dev.frogmc:thyroxine:0.0.1-alpha.9")
|
implementation("dev.frogmc:thyroxine:0.0.1-alpha.10")
|
||||||
implementation("org.ow2.asm:asm:9.7")
|
implementation("org.ow2.asm:asm:9.7")
|
||||||
implementation("org.ow2.asm:asm-commons:9.7")
|
implementation("org.ow2.asm:asm-commons:9.7")
|
||||||
implementation("org.ow2.asm:asm-tree:9.7")
|
implementation("org.ow2.asm:asm-tree:9.7")
|
||||||
|
|
|
@ -22,6 +22,7 @@ import dev.frogmc.thyroxine.RemappingStep
|
||||||
import dev.frogmc.thyroxine.Thyroxine
|
import dev.frogmc.thyroxine.Thyroxine
|
||||||
import dev.frogmc.thyroxine.api.Mapper
|
import dev.frogmc.thyroxine.api.Mapper
|
||||||
import dev.frogmc.thyroxine.api.data.MappingBundle
|
import dev.frogmc.thyroxine.api.data.MappingBundle
|
||||||
|
import dev.frogmc.thyroxine.api.data.MappingData
|
||||||
import dev.frogmc.thyroxine.provider.MojmapProvider
|
import dev.frogmc.thyroxine.provider.MojmapProvider
|
||||||
import dev.frogmc.thyroxine.writer.tiny.TinyV2Writer
|
import dev.frogmc.thyroxine.writer.tiny.TinyV2Writer
|
||||||
import net.fabricmc.fernflower.api.IFabricJavadocProvider
|
import net.fabricmc.fernflower.api.IFabricJavadocProvider
|
||||||
|
@ -225,40 +226,7 @@ class PhytotelmaPlugin : Plugin<Project> {
|
||||||
.get<String>("frog.extensions.accesswidener")?.let { name ->
|
.get<String>("frog.extensions.accesswidener")?.let { name ->
|
||||||
val aw = metadata.resolveSibling(name)
|
val aw = metadata.resolveSibling(name)
|
||||||
AccessWidener.checkAW(aw, ProjectStorage.get(project).remappedGameJarPath!!)
|
AccessWidener.checkAW(aw, ProjectStorage.get(project).remappedGameJarPath!!)
|
||||||
val mapper = Mapper(mappings) { listOf() }
|
remapAccesswidener(mappings, aw)
|
||||||
val buffer = buildString {
|
|
||||||
aw.forEachLine {
|
|
||||||
if (it.contains("\\t") && !it.startsWith("#")) {
|
|
||||||
val parts = it.split("[\\t #]+".toRegex()).toMutableList()
|
|
||||||
|
|
||||||
if (parts.size > 2) {
|
|
||||||
|
|
||||||
val type = parts[1]
|
|
||||||
when (type) {
|
|
||||||
"class" -> {
|
|
||||||
parts[2] = mapper.map(parts[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
"fields" -> {
|
|
||||||
parts[3] = mapper.mapFieldName(parts[2], parts[3], parts[4])
|
|
||||||
parts[4] = mapper.mapDesc(parts[4])
|
|
||||||
parts[3] = mapper.map(parts[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
"methods" -> {
|
|
||||||
parts[3] = mapper.mapMethodName(parts[2], parts[3], parts[4])
|
|
||||||
parts[4] = mapper.mapMethodDesc(parts[4])
|
|
||||||
parts[2] = mapper.map(parts[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appendLine(parts.joinToString("\\t"))
|
|
||||||
return@forEachLine
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appendLine(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aw.writeText(buffer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Thyroxine.remap(
|
Thyroxine.remap(
|
||||||
|
@ -328,13 +296,11 @@ class PhytotelmaPlugin : Plugin<Project> {
|
||||||
TinyV2Writer.write(storage.mappings!!,
|
TinyV2Writer.write(storage.mappings!!,
|
||||||
project.projectDir.resolve("storageMappings.tiny").writer())
|
project.projectDir.resolve("storageMappings.tiny").writer())
|
||||||
val officialStore = storage.mappings!!.forNamespaces(storage.targetNamespace!!, "official").reverse()
|
val officialStore = storage.mappings!!.forNamespaces(storage.targetNamespace!!, "official").reverse()
|
||||||
|
TinyV2Writer.write(MappingBundle(officialStore), project.projectDir.resolve("officialStore.tiny").toPath().writer())
|
||||||
val mojOfficial = MojmapProvider.get(
|
val mojOfficial = MojmapProvider.get(
|
||||||
storage.minecraftVersion!!,
|
storage.minecraftVersion!!,
|
||||||
globalCacheDir.resolve("net/minecraft/client/${storage.minecraftVersion}/client-${storage.minecraftVersion}.txt")
|
globalCacheDir.resolve("net/minecraft/client/${storage.minecraftVersion}/client-${storage.minecraftVersion}.txt")
|
||||||
).orElseThrow().reverse().renameDstNamespace(Constants.MOJMAP_NAMESPACE).also {
|
).orElseThrow().reverse().renameDstNamespace(Constants.MOJMAP_NAMESPACE).data[0].reverse()
|
||||||
TinyV2Writer.write(it,
|
|
||||||
project.projectDir.resolve("mojmap.tiny").writer())
|
|
||||||
}.data[0].reverse()
|
|
||||||
val targetPath = project.layout.buildDirectory.asFile.get().toPath().resolve("remappedMods")
|
val targetPath = project.layout.buildDirectory.asFile.get().toPath().resolve("remappedMods")
|
||||||
.resolve("dev/frogmc/phytotelma/remapped_mods")
|
.resolve("dev/frogmc/phytotelma/remapped_mods")
|
||||||
val remappedPaths = mutableListOf<Path>()
|
val remappedPaths = mutableListOf<Path>()
|
||||||
|
@ -366,16 +332,28 @@ class PhytotelmaPlugin : Plugin<Project> {
|
||||||
Thyroxine.remap(
|
Thyroxine.remap(
|
||||||
mojOfficial, artifact.file.toPath(), temp, false, defaultRemappingSteps(
|
mojOfficial, artifact.file.toPath(), temp, false, defaultRemappingSteps(
|
||||||
mojmapGameJar
|
mojmapGameJar
|
||||||
)
|
), mojmapGameJar
|
||||||
)
|
)
|
||||||
Thyroxine.remap(
|
Thyroxine.remap(
|
||||||
officialStore, temp, remappedPath, false, defaultRemappingSteps(
|
officialStore, temp, remappedPath, false, defaultRemappingSteps(
|
||||||
officialJar
|
officialJar
|
||||||
)
|
), officialJar
|
||||||
)
|
)
|
||||||
Files.deleteIfExists(temp)
|
Files.deleteIfExists(temp)
|
||||||
NestStripper.stripJij(remappedPath)
|
NestStripper.stripJij(remappedPath)
|
||||||
|
|
||||||
|
FileSystems.newFileSystem(remappedPath).use { fs ->
|
||||||
|
val metadata = fs.getPath(Constants.MOD_METADATA_FILE)
|
||||||
|
tomlParser.parse(metadata, FileNotFoundAction.READ_NOTHING)
|
||||||
|
.get<String>("frog.extensions.accesswidener")?.let { name ->
|
||||||
|
val aw = metadata.resolveSibling(name)
|
||||||
|
remapAccesswidener(mojOfficial, aw)
|
||||||
|
remapAccesswidener(officialStore, aw)
|
||||||
|
|
||||||
|
AccessWidener.checkAW(aw, ProjectStorage.get(project).remappedGameJarPath!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
project.dependencies.add(
|
project.dependencies.add(
|
||||||
target.name,
|
target.name,
|
||||||
"dev.frogmc.phytotelma.remapped_mods:$groupname:$artifactVersion" + (classifier?.let { ":$it" } ?: "")
|
"dev.frogmc.phytotelma.remapped_mods:$groupname:$artifactVersion" + (classifier?.let { ":$it" } ?: "")
|
||||||
|
@ -386,6 +364,43 @@ class PhytotelmaPlugin : Plugin<Project> {
|
||||||
System.setOut(out)
|
System.setOut(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun remapAccesswidener(mappings: MappingData, aw: Path) {
|
||||||
|
val mapper = Mapper(mappings) { listOf() }
|
||||||
|
val buffer = buildString {
|
||||||
|
aw.forEachLine {
|
||||||
|
if ((it.contains("\t") || it.contains(" ")) && !it.startsWith("#")) {
|
||||||
|
val parts = it.split("[\\t #]+".toRegex()).toMutableList()
|
||||||
|
|
||||||
|
if (parts.size > 2) {
|
||||||
|
|
||||||
|
val type = parts[1]
|
||||||
|
when (type) {
|
||||||
|
"class" -> {
|
||||||
|
parts[2] = mapper.map(parts[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
"field" -> {
|
||||||
|
parts[3] = mapper.mapFieldName(parts[2], parts[3], parts[4])
|
||||||
|
parts[4] = mapper.mapDesc(parts[4])
|
||||||
|
parts[2] = mapper.map(parts[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
"method" -> {
|
||||||
|
parts[3] = mapper.mapMethodName(parts[2], parts[3], parts[4])
|
||||||
|
parts[4] = mapper.mapMethodDesc(parts[4])
|
||||||
|
parts[2] = mapper.map(parts[2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appendLine(parts.joinToString(" "))
|
||||||
|
return@forEachLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appendLine(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aw.writeText(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var globalCacheDir: Path
|
lateinit var globalCacheDir: Path
|
||||||
val tomlParser = TomlParser()
|
val tomlParser = TomlParser()
|
||||||
|
|
|
@ -81,7 +81,7 @@ object AccessWidener {
|
||||||
}
|
}
|
||||||
FileSystems.newFileSystem(gamePath).use { fs ->
|
FileSystems.newFileSystem(gamePath).use { fs ->
|
||||||
reader.lines().toList().forEachIndexed { index, line ->
|
reader.lines().toList().forEachIndexed { index, line ->
|
||||||
val checkString = line.substring(0, line.indexOf("#"))
|
val checkString = if (line.contains("#")) line.substring(0, line.indexOf("#")) else line
|
||||||
|
|
||||||
if (checkString.isNotEmpty()) {
|
if (checkString.isNotEmpty()) {
|
||||||
val parts = checkString.split(SEPARATOR)
|
val parts = checkString.split(SEPARATOR)
|
||||||
|
@ -90,9 +90,10 @@ object AccessWidener {
|
||||||
}
|
}
|
||||||
if (parts[1] == "class") {
|
if (parts[1] == "class") {
|
||||||
val target = parts[2]
|
val target = parts[2]
|
||||||
if (fs.getPath(target).notExists()) {
|
if (fs.getPath("/$target.class").notExists()) {
|
||||||
error("AccessWidener validation failed in line ${index + 2}: $line (Invalid target)")
|
error("AccessWidener validation failed in line ${index + 2}: $line (Invalid target)")
|
||||||
}
|
}
|
||||||
|
return@forEachIndexed
|
||||||
}
|
}
|
||||||
if (parts.size < 5) {
|
if (parts.size < 5) {
|
||||||
error("AccessWidener validation failed in line ${index + 2}: $line (Declaration missing)")
|
error("AccessWidener validation failed in line ${index + 2}: $line (Declaration missing)")
|
||||||
|
@ -102,16 +103,17 @@ object AccessWidener {
|
||||||
val desc = parts[4]
|
val desc = parts[4]
|
||||||
when (parts[1]) {
|
when (parts[1]) {
|
||||||
"method" -> {
|
"method" -> {
|
||||||
val classReader = ClassReader(fs.getPath(owner).readBytes())
|
val classReader = ClassReader(fs.getPath("/$owner.class").readBytes())
|
||||||
val node = ClassNode()
|
val node = ClassNode()
|
||||||
classReader.accept(node, 0)
|
classReader.accept(node, 0)
|
||||||
if (node.methods.none { it.name.equals(name) && it.desc.equals(desc) }) {
|
if (node.methods.none { it.name.equals(name) && it.desc.equals(desc) }) {
|
||||||
error("AccessWidener validation failed in line ${index + 2}: $line (Could not find target method)")
|
val similar = "\nSimilar methods:\n ${node.methods.filter { it.name.equals(name) || it.desc.equals(desc) }.joinToString("\n") { it.name+" ${it.desc}" }}"
|
||||||
|
error("AccessWidener validation failed in line ${index + 2}: $line (Could not find target method)"+ if (node.methods.any { it.name.equals(name) || it.desc.equals(desc) }) similar else "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"field" -> {
|
"field" -> {
|
||||||
val classReader = ClassReader(fs.getPath(owner).readBytes())
|
val classReader = ClassReader(fs.getPath("/$owner.class").readBytes())
|
||||||
val node = ClassNode()
|
val node = ClassNode()
|
||||||
classReader.accept(node, 0)
|
classReader.accept(node, 0)
|
||||||
if (node.fields.none { it.name.equals(name) && it.desc.equals(desc) }) {
|
if (node.fields.none { it.name.equals(name) && it.desc.equals(desc) }) {
|
||||||
|
@ -136,7 +138,8 @@ object AccessWidener {
|
||||||
|
|
||||||
private fun readTransitiveAW(path: Path): List<String> {
|
private fun readTransitiveAW(path: Path): List<String> {
|
||||||
return path.bufferedReader(StandardCharsets.UTF_8).takeIf { HEADER.test(it.readLine() ?: "") }?.lines()
|
return path.bufferedReader(StandardCharsets.UTF_8).takeIf { HEADER.test(it.readLine() ?: "") }?.lines()
|
||||||
?.filter { it.startsWith("transitive-") }?.toList() ?: emptyList()
|
?.filter { it.startsWith("transitive-") }
|
||||||
|
?.map { it.replace("transitive-", "") }?.toList() ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readAllAWs(project: Project): Stream<Entry> {
|
private fun readAllAWs(project: Project): Stream<Entry> {
|
||||||
|
|
|
@ -22,21 +22,6 @@ class MixinAnnotationRemapper(
|
||||||
private var target: String? = null
|
private var target: String? = null
|
||||||
private var targetNode: ClassNode? = null
|
private var targetNode: ClassNode? = null
|
||||||
|
|
||||||
override fun visit(
|
|
||||||
version: Int,
|
|
||||||
access: Int,
|
|
||||||
name: String,
|
|
||||||
signature: String?,
|
|
||||||
superName: String?,
|
|
||||||
interfaces: Array<out String>?
|
|
||||||
) {
|
|
||||||
super.visit(version, access, name, signature, superName, interfaces)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitInnerClass(name: String?, outerName: String?, innerName: String?, access: Int) {
|
|
||||||
super.visitInnerClass(name, outerName, innerName, access)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
|
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
|
||||||
if (descriptor == null || descriptor != "Lorg/spongepowered/asm/mixin/Mixin;") {
|
if (descriptor == null || descriptor != "Lorg/spongepowered/asm/mixin/Mixin;") {
|
||||||
return super.visitAnnotation(descriptor, visible)
|
return super.visitAnnotation(descriptor, visible)
|
||||||
|
@ -157,29 +142,26 @@ class MixinAnnotationRemapper(
|
||||||
if (desc == null) {
|
if (desc == null) {
|
||||||
val method = owner.methods.find { it.name == methodName }
|
val method = owner.methods.find { it.name == methodName }
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
newVal = mapper.mapMethodName(
|
val newName = mapper.mapMethodName(
|
||||||
owner.name,
|
owner.name,
|
||||||
methodName,
|
methodName,
|
||||||
method.desc
|
method.desc
|
||||||
) + mapper.mapMethodDesc(method.desc)
|
)
|
||||||
println("Mapped mixin target (method) to new name: $newVal from $methodName (with found ${method.desc})")
|
newVal = newName + mapper.mapMethodDesc(method.desc)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newVal = mapper.mapMethodName(
|
val newName = mapper.mapMethodName(
|
||||||
owner.name,
|
owner.name,
|
||||||
methodName,
|
methodName,
|
||||||
desc
|
desc
|
||||||
) + mapper.mapMethodDesc(desc)
|
)
|
||||||
|
newVal = newName + mapper.mapMethodDesc(desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (name == "target") {
|
} else if (name == "target") {
|
||||||
newVal = remapMemberInfo(value, mapper)
|
newVal = remapMemberInfo(value, mapper)
|
||||||
println("target remap: $value to $newVal")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newVal != value) {
|
|
||||||
println("new annotation value: $newVal instead of $value")
|
|
||||||
}
|
|
||||||
super.visit(name, newVal)
|
super.visit(name, newVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue