Skip to content

Commit

Permalink
generate cb remap mappings and remap cb
Browse files Browse the repository at this point in the history
  • Loading branch information
MiniDigger committed Oct 6, 2023
1 parent fc64771 commit fc59983
Show file tree
Hide file tree
Showing 8 changed files with 271 additions and 7 deletions.
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/config-kotlin.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ kotlin {
}

repositories {
mavenLocal()
maven("https://repo.papermc.io/repository/maven-snapshots/") {
mavenContent {
includeModule("org.cadixdev", "mercury")
Expand Down
6 changes: 5 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ asm = "9.5"
lorenz = "0.5.8"
hypo = "2.3.0"
serialize = "1.5.1"
feather = "1.1.0"

[libraries]
asm-core = { module = "org.ow2.asm:asm", version.ref = "asm" }
Expand All @@ -19,7 +20,7 @@ cadix-lorenz-asm = { module = "org.cadixdev:lorenz-asm", version.ref = "lorenz"
cadix-lorenz-proguard = { module = "org.cadixdev:lorenz-io-proguard", version.ref = "lorenz" }
cadix-atlas = "org.cadixdev:atlas:0.2.1"
cadix-at = "org.cadixdev:at:0.1.0-rc1"
cadix-mercury = "org.cadixdev:mercury:0.1.1-paperweight-SNAPSHOT"
cadix-mercury = "org.cadixdev:mercury:0.1.1-paperweight-local-SNAPSHOT"
cadix-bombe-jar = "org.cadixdev:bombe-jar:0.4.4"

hypo-model = { module = "dev.denwav.hypo:hypo-model", version.ref = "hypo" }
Expand All @@ -33,6 +34,9 @@ slf4j-jdk14 = "org.slf4j:slf4j-jdk14:1.7.32"
lorenzTiny = "net.fabricmc:lorenz-tiny:3.0.0"
jbsdiff = "io.sigpipe:jbsdiff:1.0"

feather-core = { module = "org.parchmentmc:feather", version.ref = "feather" }
feather-gson = { module = "org.parchmentmc.feather:io-gson", version.ref = "feather" }

serialize-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialize" }
serialize-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialize" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.papermc.paperweight.core.ext
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.tasks.mache.*
import io.papermc.paperweight.tasks.mache.RemapJar
import io.papermc.paperweight.tasks.patchremapv2.GeneratePatchRemapMappings
import io.papermc.paperweight.tasks.patchremapv2.RemapCBPatches
import io.papermc.paperweight.tasks.softspoon.ApplyPatches
import io.papermc.paperweight.tasks.softspoon.ApplyPatchesFuzzy
Expand Down Expand Up @@ -41,7 +42,7 @@ open class SoftSpoonTasks(
val macheRemapJar by tasks.registering(RemapJar::class) {
group = "mache"
serverJar.set(layout.cache.resolve(SERVER_JAR_PATH))
serverMappings.set(layout.cache.resolve(SERVER_MAPPINGS))
serverMappings.set(allTasks.downloadMappings.flatMap { it.outputFile })

codebookClasspath.from(macheCodebook)
minecraftClasspath.from(macheMinecraft)
Expand Down Expand Up @@ -158,20 +159,32 @@ open class SoftSpoonTasks(

// patch remap stuff
val macheSpigotDecompileJar by tasks.registering<SpigotDecompileJar> {
group = "mache"
group = "patchremap"
inputJar.set(macheRemapJar.flatMap { it.outputJar })
fernFlowerJar.set(project.ext.craftBukkit.fernFlowerJar)
decompileCommand.set(allTasks.buildDataInfo.map { it.decompileCommand })
}

val generatePatchRemapMappings by tasks.registering(GeneratePatchRemapMappings::class) {
group = "patchremap"

minecraftClasspath.from(macheMinecraft)
serverJar.set(macheRemapJar.flatMap { it.outputJar })
paramMappings.from(macheParamMappings)
vanillaMappings.set(allTasks.downloadMappings.flatMap { it.outputFile })
spigotMappings.set(allTasks.generateSpigotMappings.flatMap { it.notchToSpigotMappings })

patchRemapMappings.set(layout.cache.resolve(SPIGOT_MOJANG_PARCHMENT_MAPPINGS))
}

val remapCBPatches by tasks.registering(RemapCBPatches::class) {
group = "paperweight"
group = "patchremap"
base.set(layout.cache.resolve(BASE_PROJECT).resolve("sources"))
//craftBukkit.set(allTasks.patchCraftBukkit.flatMap { it.outputDir })
craftBukkit.set(project.layout.cache.resolve("paperweight/taskCache/patchCraftBukkit.repo"))
outputPatchDir.set(project.layout.projectDirectory.dir("patches/remapped-cb"))
//mappingsFile.set(allTasks.patchMappings.flatMap { it.outputMappings })
mappingsFile.set(layout.cache.resolve(PATCHED_SPIGOT_MOJANG_YARN_MAPPINGS))
mappingsFile.set(layout.cache.resolve(SPIGOT_MOJANG_PARCHMENT_MAPPINGS))
}

fun afterEvaluate() {
Expand Down
3 changes: 3 additions & 0 deletions paperweight-lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ dependencies {

implementation(libs.lorenzTiny)

implementation(libs.feather.core)
implementation(libs.feather.gson)

implementation(libs.jbsdiff)

implementation(libs.codebook)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ abstract class FilterProjectDir : BaseTask() {
private fun collectFiles(dir: Path): Set<String> {
return Files.walk(dir).use { stream ->
stream.filter { it.isRegularFile() }
.map { it.relativeTo(dir).toString() }
.map { it.relativeTo(dir).invariantSeparatorsPathString }
.collect(Collectors.toUnmodifiableSet())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
package io.papermc.paperweight.tasks.patchremapv2

import com.google.gson.GsonBuilder
import dev.denwav.hypo.asm.AsmClassDataProvider
import dev.denwav.hypo.asm.hydrate.BridgeMethodHydrator
import dev.denwav.hypo.asm.hydrate.LambdaCallHydrator
import dev.denwav.hypo.asm.hydrate.LocalClassHydrator
import dev.denwav.hypo.asm.hydrate.SuperConstructorHydrator
import dev.denwav.hypo.core.HypoContext
import dev.denwav.hypo.hydrate.HydrationManager
import dev.denwav.hypo.mappings.ChangeChain
import dev.denwav.hypo.mappings.MappingsCompletionManager
import dev.denwav.hypo.mappings.contributors.CopyLambdaParametersDown
import dev.denwav.hypo.mappings.contributors.CopyMappingsDown
import dev.denwav.hypo.mappings.contributors.CopyRecordParameters
import dev.denwav.hypo.mappings.contributors.PropagateMappingsUp
import dev.denwav.hypo.model.ClassProviderRoot
import io.papermc.codebook.exceptions.UnexpectedException
import io.papermc.paperweight.tasks.*
import io.papermc.paperweight.util.*
import io.papermc.paperweight.util.constants.*
import java.io.IOException
import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.Path
import org.cadixdev.bombe.type.signature.FieldSignature
import org.cadixdev.lorenz.MappingSet
import org.cadixdev.lorenz.model.ClassMapping
import org.cadixdev.lorenz.model.TopLevelClassMapping
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.*
import org.parchmentmc.feather.io.gson.MDCGsonAdapterFactory
import org.parchmentmc.feather.io.gson.SimpleVersionAdapter
import org.parchmentmc.feather.mapping.MappingDataContainer
import org.parchmentmc.feather.mapping.VersionedMappingDataContainer
import org.parchmentmc.feather.util.SimpleVersion

@CacheableTask
abstract class GeneratePatchRemapMappings : BaseTask() {

@get:CompileClasspath
abstract val minecraftClasspath: ConfigurableFileCollection

@get:PathSensitive(PathSensitivity.NONE)
@get:InputFiles
abstract val paramMappings: ConfigurableFileCollection

@get:PathSensitive(PathSensitivity.NONE)
@get:InputFile
abstract val serverJar: RegularFileProperty

@get:InputFile
@get:PathSensitive(PathSensitivity.NONE)
abstract val vanillaMappings: RegularFileProperty

@get:InputFile
@get:PathSensitive(PathSensitivity.NONE)
abstract val spigotMappings: RegularFileProperty

@get:OutputFile
abstract val patchRemapMappings: RegularFileProperty

@TaskAction
fun run() {
val mergedMappings = merge(vanillaMappings.path, spigotMappings.path, paramMappings.singleFile.toPath())

// run hypo
val ctx: HypoContext

try {
ctx = HypoContext.builder()
.withProvider(AsmClassDataProvider.of(ClassProviderRoot.fromJar(serverJar.convertToPath())))
.withContextProvider(AsmClassDataProvider.of(ClassProviderRoot.fromJars(*minecraftClasspath.files.map { it.toPath() }
.toTypedArray())))
.withContextProvider(AsmClassDataProvider.of(ClassProviderRoot.ofJdk()))
.build()
} catch (e: IOException) {
throw UnexpectedException("Failed to open jar files", e)
}

try {
HydrationManager.createDefault()
.register(BridgeMethodHydrator.create())
.register(SuperConstructorHydrator.create())
.register(LambdaCallHydrator.create())
.register(LocalClassHydrator.create())
.hydrate(ctx)
} catch (e: IOException) {
throw UnexpectedException("Failed to hydrate data model", e)
}

// Fill in any missing mapping information
val completedParamMappings = ChangeChain.create()
.addLink(
CopyMappingsDown.createWithoutOverwrite(),
CopyLambdaParametersDown.createWithoutOverwrite(),
CopyRecordParameters.create(),
PropagateMappingsUp.create()
)
.applyChain(mergedMappings, MappingsCompletionManager.create(ctx))

try {
MappingFormats.TINY.write(completedParamMappings, patchRemapMappings.convertToPath(), SPIGOT_NAMESPACE, NEW_DEOBF_NAMESPACE)
} catch (e: IOException) {
throw UnexpectedException("Failed to write mappings", e)
}
}

private fun merge(mojangPath: Path, spigotPath: Path, parchmentPath: Path): MappingSet {
// mojang -> obf
val mojangMappings = MappingFormats.PROGUARD.createReader(mojangPath).use { it.read() }
// obf -> spigot
val spigotMappings = MappingFormats.TINY.read(spigotPath, OBF_NAMESPACE, SPIGOT_NAMESPACE)

val gson = GsonBuilder()
.registerTypeAdapterFactory(MDCGsonAdapterFactory())
.registerTypeAdapter(SimpleVersion::class.java, SimpleVersionAdapter())
.create()

val mappings: MappingDataContainer
try {
FileSystems.newFileSystem(parchmentPath).use { fs ->
val jsonFile = fs.getPath("/parchment.json")
Files.newBufferedReader(jsonFile).use { reader ->
mappings = gson.fromJson(reader, VersionedMappingDataContainer::class.java)
}
}
} catch (e: IOException) {
throw UnexpectedException("Failed to read param mappings file", e)
}

// mojang -> mojang+parchment
val parchmentMappings = this.toLorenz(mappings)

// result: spigot -> mojang+parchment
val result = MappingSet.create()

// merge
mojangMappings.topLevelClassMappings.filterNot { it.obfuscatedName.endsWith("package-info") }.forEach { mojangClass ->
val spigotClass = spigotMappings.getTopLevelClassMapping(mojangClass.deobfuscatedName).orElse(null)
if (spigotClass == null) {
//println("cant find spigot class for ${mojangClass.deobfuscatedName} - ${mojangClass.obfuscatedName}")
return@forEach
}
val parchmentClass = parchmentMappings.getTopLevelClassMapping(mojangClass.obfuscatedName).orElse(null)
if (parchmentClass == null) {
println("cant find parchmentClass class for ${mojangClass.obfuscatedName} - ${mojangClass.deobfuscatedName}")
return@forEach
}
val resultClass = result.createTopLevelClassMapping(spigotClass.deobfuscatedName, mojangClass.obfuscatedName)

mergeMethodsAndFields(resultClass, mojangClass, spigotClass, parchmentClass)

mergeInnerClass(mojangClass, spigotClass, resultClass, parchmentClass)
}

return result
}

private fun mergeInnerClass(
mojangClass: ClassMapping<*, *>,
spigotClass: ClassMapping<*, *>,
resultClass: ClassMapping<*, *>,
parchmentClass: TopLevelClassMapping
) {
mojangClass.innerClassMappings.forEach { innerMojangClass ->
val innerSpigotClass = spigotClass.getInnerClassMapping(innerMojangClass.deobfuscatedName).orElse(null)
if (innerSpigotClass == null) {
//println("cant find inner spigot class for ${innerMojangClass.deobfuscatedName} - ${innerMojangClass.obfuscatedName}")
return@forEach
}
val innerParchmentClass = parchmentClass.getInnerClassMapping(innerMojangClass.obfuscatedName).orElse(null)
if (innerParchmentClass == null) {
println("cant find innerParchmentClass for ${innerMojangClass.obfuscatedName} - ${innerMojangClass.deobfuscatedName}")
return@forEach
}
val innerResultClass = resultClass.createInnerClassMapping(innerSpigotClass.deobfuscatedName, innerMojangClass.obfuscatedName)

mergeMethodsAndFields(innerResultClass, innerMojangClass, innerSpigotClass, innerParchmentClass)

mergeInnerClass(innerMojangClass, innerSpigotClass, innerResultClass, parchmentClass)
}
}

private fun mergeMethodsAndFields(
resultClass: ClassMapping<*, *>,
mojangClass: ClassMapping<*, *>,
spigotClass: ClassMapping<*, *>,
parchmentClass: ClassMapping<*, *>
) {
mojangClass.fieldMappings.forEach { mojangField ->
val spigotField = spigotClass.getFieldMapping(mojangField.deobfuscatedName).orElse(null)
if (spigotField == null) {
//println("cant find spigot field for ${mojangField.deobfuscatedName} - ${mojangField.obfuscatedName}")
return@forEach
}
val resultField = resultClass.createFieldMapping(spigotField.deobfuscatedSignature, mojangField.obfuscatedName)
resultField.deobfuscatedName = mojangField.obfuscatedName
}

mojangClass.methodMappings.forEach { mojangMethod ->
val spigotMethod = spigotClass.getMethodMapping(mojangMethod.deobfuscatedName, mojangMethod.deobfuscatedDescriptor).orElse(null)
if (spigotMethod == null) {
//println("cant find spigot method for ${mojangMethod.deobfuscatedName} - ${mojangMethod.obfuscatedName}")
return@forEach
}
val parchmentMethod = parchmentClass.getMethodMapping(mojangMethod.obfuscatedName, mojangMethod.obfuscatedDescriptor).orElse(null)
if (parchmentMethod == null) {
//println("cant find parchmentMethod for ${mojangMethod.deobfuscatedName} - ${mojangMethod.obfuscatedName}")
return@forEach
}
val resultMethod = resultClass.createMethodMapping(spigotMethod.deobfuscatedName, spigotMethod.deobfuscatedDescriptor)
resultMethod.setDeobfuscatedName(mojangMethod.obfuscatedName)

parchmentMethod.parameterMappings.forEach {
resultMethod.createParameterMapping(it.index, it.deobfuscatedName)
}
}
}

private fun toLorenz(container: MappingDataContainer): MappingSet {
val mappings = MappingSet.create()

for (aClass in container.classes) {
val classMapping = mappings.getOrCreateClassMapping(aClass.name)
for (method in aClass.methods) {
val methodMapping = classMapping.getOrCreateMethodMapping(method.name, method.descriptor)
for (param in method.parameters) {
methodMapping.getOrCreateParameterMapping(param.index.toInt()).setDeobfuscatedName(param.name)
}
}
for (field in aClass.fields) {
classMapping.getOrCreateFieldMapping(FieldSignature.of(field.name, field.descriptor))
}
}

return mappings
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ abstract class RemapCBPatches : BaseTask() {
fun run() {
val workDir = layout.cache.resolve(REMAPPED_CB).ensureClean()
val patches = outputPatchDir.convertToPath().ensureClean()
val mappings = MappingFormats.TINY.read(mappingsFile.convertToPath(), SPIGOT_NAMESPACE, DEOBF_NAMESPACE)
val mappings = MappingFormats.TINY.read(mappingsFile.convertToPath(), SPIGOT_NAMESPACE, NEW_DEOBF_NAMESPACE)

val configFiles = project.project(":paper-server").configurations["runtimeClasspath"].resolve().map { it.toPath() }
val classpath = configFiles + listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,12 @@ const val PATCHED_SPIGOT_MOJANG_YARN_MAPPINGS = "$MAPPINGS_DIR/spigot-mojang+yar
const val PATCHED_SPIGOT_MOJANG_YARN_SOURCE_MAPPINGS = "$MAPPINGS_DIR/spigot-mojang+yarn-patched-source.tiny"
const val REOBF_MOJANG_SPIGOT_MAPPINGS = "$MAPPINGS_DIR/mojang+yarn-spigot-reobf.tiny"
const val PATCHED_REOBF_MOJANG_SPIGOT_MAPPINGS = "$MAPPINGS_DIR/mojang+yarn-spigot-reobf-patched.tiny"
const val SPIGOT_MOJANG_PARCHMENT_MAPPINGS = "$MAPPINGS_DIR/spigot-mojang+parchment.tiny"

const val OBF_NAMESPACE = "official"
const val SPIGOT_NAMESPACE = "spigot"
const val DEOBF_NAMESPACE = "mojang+yarn"
const val NEW_DEOBF_NAMESPACE = "mojang+parchment"

private const val DATA_PATH = "$PAPER_PATH/data"
const val MC_MANIFEST = "$DATA_PATH/McManifest.json"
Expand Down

0 comments on commit fc59983

Please sign in to comment.