diff options
-rw-r--r-- | src/main/kotlin/mcprepack/App.kt | 73 | ||||
-rw-r--r-- | src/main/kotlin/mcprepack/CSVFile.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/mcprepack/ParseMethodDescriptor.kt | 112 | ||||
-rw-r--r-- | src/main/kotlin/mcprepack/ProguardWriter.kt | 35 |
4 files changed, 209 insertions, 12 deletions
diff --git a/src/main/kotlin/mcprepack/App.kt b/src/main/kotlin/mcprepack/App.kt index 86764e0..688716b 100644 --- a/src/main/kotlin/mcprepack/App.kt +++ b/src/main/kotlin/mcprepack/App.kt @@ -110,7 +110,7 @@ fun main(): Unit = lifecycle("Repacking") { val newTiny = TinyFile(TinyHeader(listOf("official", "intermediary", "named"), 2, 0, mapOf()), tinyFile.classEntries.map { TinyClass(it.classNames + listOf(it.classNames[1]), it.methods.map { method -> - val mcpMethod = methods.map.find { it["searge"] == method.methodNames[1] } + val mcpMethod = methods.indexedBySearge[method.methodNames[1]] TinyMethod(method.methodDescriptorInFirstNamespace, method.methodNames + listOf(mcpMethod?.get("name") ?: method.methodNames[1]), method.parameters, @@ -118,7 +118,7 @@ fun main(): Unit = lifecycle("Repacking") { method.comments + (mcpMethod?.get("desc")?.let { listOf(it) } ?: listOf())) // TODO parameter names and better comments? }, it.fields.map { field -> - val mcpField = fields.map.find { it["searge"] == field.fieldNames[1] } + val mcpField = fields.indexedBySearge[field.fieldNames[1]] TinyField(findFieldDescriptorInMergedJar(it.classNames[0], field.fieldNames[0]), field.fieldNames + listOf(mcpField?.get("name") ?: field.fieldNames[1]), field.comments + (mcpField?.get("desc")?.let { listOf(it) } ?: listOf())) @@ -154,7 +154,7 @@ fun main(): Unit = lifecycle("Repacking") { // TODO merge binpatches somehow? not sure how that would work, maybe look at essential loom fun createBinPatchSubJar(dist: String): Path { - val basePath = binpatchesLegacy.getPath("binpatch/client") + val basePath = binpatchesLegacy.getPath("binpatch/$dist") val modernPatchJar = WorkContext.file("binpatches-modern", "jar") modernPatchJar.deleteExisting() val patchJarFs = FileSystems.newFileSystem(modernPatchJar, mapOf("create" to true)) @@ -180,6 +180,35 @@ fun main(): Unit = lifecycle("Repacking") { createBinPatchSubJar("server") } + val proguardLog = lifecycle("Create Proguard Obfuscation Log") { + val x = WorkContext.file("proguard", "txt") + x.bufferedWriter().use { + val pro = ProguardWriter(it) + val tinyFile = TinyV2Reader.read(tinyV2Enhanced) + tinyFile.classEntries.forEach { tinyClass -> + pro.visitClass(tinyClass.classNames[2], tinyClass.classNames[0]) + tinyClass.fields.forEach { field -> + val fd = FieldDescriptor.parseFieldDescriptor(field.fieldDescriptorInFirstNamespace) + pro.visitField( + field.fieldNames[2], + field.fieldNames[0], + fd.type.mapClassName(tinyFile).toProguardString() + ) + } + tinyClass.methods.forEach { method -> + val md = MethodDescriptor.parseMethodDescriptor(method.methodDescriptorInFirstNamespace) + pro.visitMethod( + method.methodNames[2], method.methodNames[0], + md.arguments.map { it.mapClassName(tinyFile) } + .map { it.toProguardString() }, + md.returnType.mapClassName(tinyFile).toProguardString() + ) + } + } + } + x + } + val modernForgeInstaller = lifecycle("Create Modern Forge Installer") { val x = WorkContext.file("modern-forge-installer", "jar") x.deleteExisting() @@ -221,17 +250,42 @@ fun main(): Unit = lifecycle("Repacking") { }) }) addProperty("universal", "net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9:universal@jar") - addProperty("sources", "net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9:sources@jar") + addProperty("sources", "net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9:universal@jar") addProperty("spec", 2)//Hahaha, yes, I follow the spec, so true add("libraries", JsonArray().apply { legacyDevJson["libraries"].asJsonArray.forEach { add(it.asJsonObject["name"]) } }) + add("runs", JsonObject().apply { + add("client", JsonObject().apply { + addProperty("name", "client") + addProperty("main", "net.minecraft.launchwrapper.Launch") + add("parents", JsonArray()) + add("args", JsonArray().apply { + add("--accessToken") + add("undefined") + add("--assetsIndex") + add("{assets_index}") + add("--assetsDir") + add("{assets_root}") + add("--tweakClass") + add("net.minecraftforge.fml.common.launcher.FMLTweaker") + }) + add("jvmArgs", JsonArray()) + addProperty("client", true) + addProperty("forceExit", true) + add("env", JsonObject()) + add("props", JsonObject()) + }) + }) + addProperty("spec", 2) })) userdevModern.getPath("/joined.lzma").outputStream().use { binpatchesModernClient.inputStream().copyTo(LzmaOutputStream(it, Encoder())) } + userdevModern.getPath("/META-INF").createDirectories() + legacyForgeUniversal.getPath("forge_at.cfg").copyTo(userdevModern.getPath("/META-INF/accesstransformer.cfg")) userdevModern.close() x } @@ -243,7 +297,7 @@ fun main(): Unit = lifecycle("Repacking") { mcpConfigModern.getPath("config.json").writeText(gson.toJson(JsonObject().apply { addProperty("spec", 3) addProperty("version", "1.8.9") - addProperty("official", false) + addProperty("official", true) addProperty("encoding", "UTF-8") add("data", JsonObject().apply { addProperty("mappings", "config/joined.tsrg") @@ -261,13 +315,6 @@ fun main(): Unit = lifecycle("Repacking") { addProperty("version", "1.8.9") addProperty("name", "rename") }) - /* - add(JsonObject().apply { - addProperty("type", "rename") - addProperty("input", "{mergeOutput}")// TODO maybe strip? honestly not sure - addProperty("libraries", "{listLibrariesOutput}") - addProperty("mappings", "{mappings}") - })*/ }) for (dist in listOf("client", "server")) { add(dist, JsonArray().apply { @@ -361,6 +408,8 @@ fun main(): Unit = lifecycle("Repacking") { modernForgeUserdev.copyTo(mavenFile("forge", "jar", "userdev")) modernForgeUserdev.copyTo(mavenFile("forge", "jar")) modernForgeInstaller.copyTo(mavenFile("forge", "jar", "installer")) + + proguardLog.copyTo(mavenFile("official", "txt")) } } diff --git a/src/main/kotlin/mcprepack/CSVFile.kt b/src/main/kotlin/mcprepack/CSVFile.kt index 6463fc7..1ddc03f 100644 --- a/src/main/kotlin/mcprepack/CSVFile.kt +++ b/src/main/kotlin/mcprepack/CSVFile.kt @@ -2,4 +2,5 @@ package mcprepack data class CSVFile(val headers: List<String>, val entries: List<List<String>>) { val map = entries.map { headers.zip(it).toMap() } + val indexedBySearge = map.associateBy { it["searge"] } } diff --git a/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt b/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt new file mode 100644 index 0000000..a3d5717 --- /dev/null +++ b/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt @@ -0,0 +1,112 @@ +package mcprepack + +import net.fabricmc.stitch.commands.tinyv2.TinyFile +import java.io.StringReader + +sealed interface TypeDescriptor { + fun mapClassName(tinyFile: TinyFile): TypeDescriptor { + return when (this) { + is Class -> + Class(tinyFile.mapClassesByFirstNamespace()[this.name]?.classNames?.get(2) ?: this.name) + + else -> this + } + } + + fun toProguardString(): String { + return when (this) { + is Array -> this.elementType.toProguardString() + "[]" + Boolean -> "boolean" + Byte -> "byte" + Char -> "char" + is Class -> this.name.replace("/", ".") + Double -> "double" + Float -> "float" + Int -> "int" + Long -> "long" + Short -> "short" + Void -> "void" + } + } + + sealed interface FieldDescriptor : TypeDescriptor + object Void : TypeDescriptor + object Double : FieldDescriptor + object Boolean : FieldDescriptor + object Float : FieldDescriptor + object Int : FieldDescriptor + object Long : FieldDescriptor + object Short : FieldDescriptor + object Byte : FieldDescriptor + object Char : FieldDescriptor + data class Class(val name: String) : FieldDescriptor + data class Array(val elementType: TypeDescriptor) : FieldDescriptor +} + +data class FieldDescriptor( + val type: TypeDescriptor.FieldDescriptor +) { + companion object { + fun parseFieldDescriptor(descriptor: String) = + FieldDescriptor(readType(StringReader(descriptor)) as? TypeDescriptor.FieldDescriptor ?: error("Cannot have void as a field type")) + } +} + +data class MethodDescriptor( + val arguments: List<TypeDescriptor.FieldDescriptor>, + val returnType: TypeDescriptor +) { + companion object { + fun parseMethodDescriptor(descriptor: String): MethodDescriptor { + val reader = StringReader(descriptor) + require(reader.readChar() == '(') + val arguments = mutableListOf<TypeDescriptor.FieldDescriptor>() + while (reader.peek() != ')') { + arguments.add( + readType(reader) as? TypeDescriptor.FieldDescriptor ?: error("Cannot have void type as argument") + ) + } + reader.readChar() // Consume the ')' + return MethodDescriptor(arguments, readType(reader)) + } + } +} + +fun StringReader.readChar() = CharArray(1).let { + if (read(it) < 0) null + else it[0] +} + +fun StringReader.readUntil(search: Char): String? { + val s = StringBuilder() + while (true) { + val justRead = readChar() ?: return null + if (justRead == search) return s.toString() + s.append(justRead) + } +} + +fun StringReader.peek(): Char? { + mark(0) + val x = readChar() + reset() + return x +} + + +fun readType(reader: StringReader): TypeDescriptor { + return when (reader.readChar()) { + 'L' -> TypeDescriptor.Class(reader.readUntil(';') ?: error("Unfinished class type descriptor")) + 'V' -> TypeDescriptor.Void + 'Z' -> TypeDescriptor.Boolean + 'B' -> TypeDescriptor.Byte + 'I' -> TypeDescriptor.Int + 'D' -> TypeDescriptor.Double + 'J' -> TypeDescriptor.Long + 'S' -> TypeDescriptor.Short + 'F' -> TypeDescriptor.Float + 'C' -> TypeDescriptor.Char + '[' -> TypeDescriptor.Array(readType(reader)) + else -> error("Unknown or unfinished type descriptor") + } +} diff --git a/src/main/kotlin/mcprepack/ProguardWriter.kt b/src/main/kotlin/mcprepack/ProguardWriter.kt new file mode 100644 index 0000000..64d84f8 --- /dev/null +++ b/src/main/kotlin/mcprepack/ProguardWriter.kt @@ -0,0 +1,35 @@ +package mcprepack + +import java.io.Writer + +data class ProguardWriter(val writer: Writer) { + fun visitClass(sourceName: String, targetName: String) { + writer.write(sourceName) + writer.write(" -> ") + writer.write(targetName) + writer.write(":\n") + } + + fun visitField(sourceName: String, targetName: String, proguardType: String) { + writer.write(" ") + writer.write(proguardType) + writer.write(" ") + writer.write(sourceName) + writer.write(" -> ") + writer.write(targetName) + writer.write("\n") + } + + fun visitMethod(sourceName: String, targetName: String, arguments: List<String>, returnType: String) { + writer.write(" ") + writer.write(returnType) + writer.write(" ") + writer.write(sourceName) + writer.write("(") + writer.write(arguments.joinToString(",")) + writer.write(") -> ") + writer.write(targetName) + writer.write("\n") + } + +}
\ No newline at end of file |