using parchment: parameter names & javadoc; use vineflower for source generation #1

Merged
owlsys merged 4 commits from parchment into mistress 2024-05-18 07:05:46 -04:00
5 changed files with 78 additions and 34 deletions

View file

@ -21,7 +21,7 @@ repositories {
} }
dependencies { dependencies {
implementation("org.ecorous.esnesnon:mojmap-patcher:1.0.0-SNAPSHOT") implementation("org.ecorous.esnesnon:nonsense-remapper:1.0.0-SNAPSHOT")
implementation("com.google.code.gson:gson:2.10.1") implementation("com.google.code.gson:gson:2.10.1")
implementation("org.vineflower:vineflower:1.10.1") implementation("org.vineflower:vineflower:1.10.1")
testImplementation(kotlin("test")) testImplementation(kotlin("test"))

View file

@ -2,12 +2,14 @@ package org.ecorous.esnesnon.gradle
import net.fabricmc.fernflower.api.IFabricJavadocProvider import net.fabricmc.fernflower.api.IFabricJavadocProvider
import org.ecorous.esnesnon.gradle.vineflower.ParchmentJavadocProvider import org.ecorous.esnesnon.gradle.vineflower.ParchmentJavadocProvider
import org.ecorous.esnesnon.nonsense_remapper.provider.ParchmentProvider
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler import org.jetbrains.java.decompiler.main.Fernflower
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger
import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences
import java.io.PrintStream
import java.net.URI import java.net.URI
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.deleteExisting import kotlin.io.path.deleteExisting
@ -41,21 +43,30 @@ class NonsenseGradlePlugin : Plugin<Project> {
} }
} }
project.task("genSources").apply { project.task("genSources").apply {
group = "nonsense" group = "nonsense"
doFirst { doFirst {
val fileName = remappedGameJarPath.fileName.toString() val fileName = remappedGameJarPath.fileName.toString()
val output = remappedGameJarPath.resolveSibling(fileName.substring(0, fileName.length-4)+"-sources.jar") val output =
if (output.exists()){ remappedGameJarPath.resolveSibling(fileName.substring(0, fileName.length - 13) + "-sources.jar")
if (output.exists()) {
println("Output $output already exists, deleting!") println("Output $output already exists, deleting!")
output.deleteExisting() output.deleteExisting()
} }
val options = mutableMapOf<String, Any>()
println("Preparing Parchment...")
val parchment = ParchmentProvider.getParchment(
minecraftVersion,
parchmentVersion,
project.gradle.gradleUserHomeDir.resolve("nonsense-gradle/org/parchmentmc/parchment/$minecraftVersion/$parchmentVersion/")
.toPath()
)
options[IFabricJavadocProvider.PROPERTY_NAME] = ParchmentJavadocProvider(parchment)
println("Decompiling...") println("Decompiling...")
val logger = PrintStreamLogger(System.out) val logger = PrintStreamLogger(PrintStream(System.out))
val options = mapOf( options.putAll(
IFabricJavadocProvider.PROPERTY_NAME to ParchmentJavadocProvider(), mapOf(
IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES to "1", IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES to "1",
IFernflowerPreferences.BYTECODE_SOURCE_MAPPING to "1", IFernflowerPreferences.BYTECODE_SOURCE_MAPPING to "1",
IFernflowerPreferences.REMOVE_SYNTHETIC to "1", IFernflowerPreferences.REMOVE_SYNTHETIC to "1",
@ -63,14 +74,15 @@ class NonsenseGradlePlugin : Plugin<Project> {
IFernflowerPreferences.THREADS to Runtime.getRuntime().availableProcessors().toString(), IFernflowerPreferences.THREADS to Runtime.getRuntime().availableProcessors().toString(),
IFernflowerPreferences.INDENT_STRING to "\t" IFernflowerPreferences.INDENT_STRING to "\t"
) )
)
val decomp = BaseDecompiler(SingleFileSaver(output.toFile()), val decomp = Fernflower(
options, logger) SingleFileSaver(output.toFile()),
options, logger
)
decomp.addSource(remappedGameJarPath.toFile()) decomp.addSource(remappedGameJarPath.toFile())
decomp.decompileContext() decomp.decompileContext()
println("Setting up nonsense...")
println("Imagine actually doing stuff")
} }
} }
@ -89,5 +101,6 @@ class NonsenseGradlePlugin : Plugin<Project> {
companion object { companion object {
lateinit var minecraftVersion: String lateinit var minecraftVersion: String
lateinit var remappedGameJarPath: Path lateinit var remappedGameJarPath: Path
lateinit var parchmentVersion: String
} }
} }

View file

@ -28,14 +28,24 @@ object VersionChecker {
} }
downloadDirectory.createDirectories() downloadDirectory.createDirectories()
val raw = rawDownload(clientData.url) val raw = rawDownload(clientData.url)
if (!downloadFile.exists()) {
downloadFile.createFile()
}
downloadFile.writeBytes(raw) downloadFile.writeBytes(raw)
savePomFile(version, downloadDirectory)
println("Downloaded client to $downloadFile") println("Downloaded client to $downloadFile")
return downloadFile return downloadFile
} }
private fun savePomFile(version: String, dir: Path){
val content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\" xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
"\t\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
"\t<modelVersion>4.0.0</modelVersion>\n" +
"\t<groupId>net.minecraft</groupId>\n" +
"\t<artifactId>client</artifactId>\n" +
"\t<version>$version</version>\n" +
"</project>"
dir.resolve("client-$version.pom").writeText(content)
}
fun getDependencies(version: String, action: (String) -> Unit) { fun getDependencies(version: String, action: (String) -> Unit) {
fetchVersionData(version).libraries.map { it.name }.forEach { fetchVersionData(version).libraries.map { it.name }.forEach {
action.invoke(it) action.invoke(it)

View file

@ -2,13 +2,21 @@ package org.ecorous.esnesnon.gradle.ext
import org.ecorous.esnesnon.gradle.NonsenseGradlePlugin import org.ecorous.esnesnon.gradle.NonsenseGradlePlugin
import org.ecorous.esnesnon.gradle.VersionChecker import org.ecorous.esnesnon.gradle.VersionChecker
import org.ecorous.esnesnon.mojmap_patcher.MojMapPatcher import org.ecorous.esnesnon.nonsense_remapper.NonsenseRemapper
import org.ecorous.esnesnon.nonsense_remapper.api.Mapper
import org.ecorous.esnesnon.nonsense_remapper.parser.ProguardParser
import org.ecorous.esnesnon.nonsense_remapper.provider.MojmapProvider
import org.ecorous.esnesnon.nonsense_remapper.provider.ParchmentProvider
import org.gradle.api.Project import org.gradle.api.Project
import kotlin.io.path.notExists import kotlin.io.path.notExists
fun Project.minecraft(version: String) { fun Project.minecraft(
version: String,
parchmentVersion: String = ParchmentProvider.findForMinecraftVersion(version)
): Project { // return self to allow for chaining
if (VersionChecker.validateVersion(version)) { if (VersionChecker.validateVersion(version)) {
NonsenseGradlePlugin.minecraftVersion = version NonsenseGradlePlugin.minecraftVersion = version
NonsenseGradlePlugin.parchmentVersion = parchmentVersion
println("Valid version! $version") println("Valid version! $version")
val clientData = VersionChecker.fetchClientDownload(version) val clientData = VersionChecker.fetchClientDownload(version)
println("Client data: ${clientData.url}") println("Client data: ${clientData.url}")
@ -20,15 +28,23 @@ fun Project.minecraft(version: String) {
NonsenseGradlePlugin.remappedGameJarPath = remappedJar NonsenseGradlePlugin.remappedGameJarPath = remappedJar
println("Time to setup Minecraft!") println("Time to setup Minecraft!")
if (remappedJar.notExists()) { if (remappedJar.notExists()) {
MojMapPatcher.run(version, clientJar, remappedJar, true) val mapper = Mapper(ProguardParser.read(MojmapProvider.get(version).orElseThrow()).reverse())
val paramMappings = ParchmentProvider.getParchment(
version, parchmentVersion,
gradle.gradleUserHomeDir.resolve("nonsense-gradle/org/parchmentmc/parchment/$version/$parchmentVersion")
.toPath()
)
NonsenseRemapper.remap(mapper, clientJar, remappedJar, true, paramMappings)
} }
VersionChecker.getDependencies(version){ VersionChecker.getDependencies(version) {
dependencies.add("implementation", it) dependencies.add("implementation", it)
} }
dependencies.add("implementation", files(remappedJar)) dependencies.add("implementation", "net.minecraft:client:$version:remapped")
//dependencies.add("implementation", files(remappedJar))
} else { } else {
println("Invalid version! $version") println("Invalid version! $version")
error("Invalid minecraft version provided: $version") error("Invalid minecraft version provided: $version")
} }
println("Minecraft!") println("Minecraft!")
return this
} }

View file

@ -1,20 +1,25 @@
package org.ecorous.esnesnon.gradle.vineflower package org.ecorous.esnesnon.gradle.vineflower
import net.fabricmc.fernflower.api.IFabricJavadocProvider import net.fabricmc.fernflower.api.IFabricJavadocProvider
import org.ecorous.esnesnon.nonsense_remapper.api.data.Parchment
import org.jetbrains.java.decompiler.struct.StructClass import org.jetbrains.java.decompiler.struct.StructClass
import org.jetbrains.java.decompiler.struct.StructField import org.jetbrains.java.decompiler.struct.StructField
import org.jetbrains.java.decompiler.struct.StructMethod import org.jetbrains.java.decompiler.struct.StructMethod
class ParchmentJavadocProvider : IFabricJavadocProvider { class ParchmentJavadocProvider(private val parchment: Parchment) : IFabricJavadocProvider {
override fun getClassDoc(structClass: StructClass): String { override fun getClassDoc(structClass: StructClass): String? {
return "" return parchment.getClass(structClass.qualifiedName).orElse(null)?.javadoc?.joinToString { "\n" }
Outdated
Review

might be nicer in kotlin to do .orElse(null) and use ?.
or at least combine the map calls into one as it seems unnecessary to split them

might be nicer in kotlin to do .orElse(null) and use ?. or at least combine the map calls into one as it seems unnecessary to split them
} }
override fun getFieldDoc(structClass: StructClass, structField: StructField): String { override fun getFieldDoc(structClass: StructClass, structField: StructField): String? {
return "" return parchment.getClass(structClass.qualifiedName)
.flatMap { it.getField(structField.name, structField.descriptor) }
.orElse(null)?.javadoc?.joinToString { "\n" }
} }
override fun getMethodDoc(structClass: StructClass, structMethod: StructMethod): String { override fun getMethodDoc(structClass: StructClass, structMethod: StructMethod): String? {
return "" return parchment.getClass(structClass.qualifiedName)
.flatMap { it.getMethod(structMethod.name, structMethod.descriptor) }
.orElse(null)?.javadoc?.joinToString { "\n" }
} }
} }