Attempt to correct mappings around SpecialSource2's synthetic mangling
This commit is contained in:
parent
141567c6c4
commit
db45b1803b
29 changed files with 1339 additions and 781 deletions
|
@ -16,25 +16,32 @@ repositories {
|
|||
mavenCentral()
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||
maven("https://files.minecraftforge.net/maven/")
|
||||
maven("https://maven.fabricmc.net/")
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.apache.httpcomponents:httpclient:4.5.12")
|
||||
implementation("org.apache.httpcomponents:httpclient:4.5.13")
|
||||
|
||||
// Utils
|
||||
implementation("net.sf.opencsv:opencsv:2.3")
|
||||
implementation("com.opencsv:opencsv:5.3")
|
||||
implementation("com.github.salomonbrys.kotson:kotson:2.5.0")
|
||||
|
||||
// ASM for inspection
|
||||
implementation("org.ow2.asm:asm:8.0.1")
|
||||
val asmVersion = "9.0"
|
||||
implementation("org.ow2.asm:asm:$asmVersion")
|
||||
implementation("org.ow2.asm:asm-tree:$asmVersion")
|
||||
|
||||
// Cadix
|
||||
implementation("org.cadixdev:lorenz:0.5.5")
|
||||
implementation("org.cadixdev:lorenz-asm:0.5.5")
|
||||
val lorenzVersion = "0.5.6"
|
||||
implementation("org.cadixdev:lorenz:$lorenzVersion")
|
||||
implementation("org.cadixdev:lorenz-asm:$lorenzVersion")
|
||||
implementation("org.cadixdev:lorenz-io-proguard:$lorenzVersion")
|
||||
implementation("org.cadixdev:atlas:0.2.0")
|
||||
implementation("org.cadixdev:at:0.1.0-SNAPSHOT")
|
||||
implementation("org.cadixdev:at:0.1.0-rc1")
|
||||
implementation("org.cadixdev:mercury:0.1.0-PW0-SNAPSHOT")
|
||||
|
||||
implementation("org.cadixdev:mercury:0.1.0-SNAPSHOT")
|
||||
implementation("net.fabricmc:lorenz-tiny:3.0.0")
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
|
|
|
@ -30,12 +30,10 @@ import com.github.salomonbrys.kotson.get
|
|||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.JsonObject
|
||||
import io.papermc.paperweight.ext.PaperweightExtension
|
||||
import io.papermc.paperweight.tasks.AddMissingSpigotClassMappings
|
||||
import io.papermc.paperweight.tasks.AddAdditionalSpigotMappings
|
||||
import io.papermc.paperweight.tasks.ApplyDiffPatches
|
||||
import io.papermc.paperweight.tasks.ApplyGitPatches
|
||||
import io.papermc.paperweight.tasks.ApplyMcpPatches
|
||||
import io.papermc.paperweight.tasks.ApplyPaperPatches
|
||||
import io.papermc.paperweight.tasks.ApplySourceAt
|
||||
import io.papermc.paperweight.tasks.DecompileVanillaJar
|
||||
import io.papermc.paperweight.tasks.DownloadMcLibraries
|
||||
import io.papermc.paperweight.tasks.DownloadMcpFiles
|
||||
|
@ -47,18 +45,17 @@ import io.papermc.paperweight.tasks.ExtractMappings
|
|||
import io.papermc.paperweight.tasks.ExtractMcp
|
||||
import io.papermc.paperweight.tasks.Filter
|
||||
import io.papermc.paperweight.tasks.FilterExcludes
|
||||
import io.papermc.paperweight.tasks.GenerateSpigotSrgs
|
||||
import io.papermc.paperweight.tasks.GenerateSrgs
|
||||
import io.papermc.paperweight.tasks.FixJar
|
||||
import io.papermc.paperweight.tasks.GenerateSpigotMappings
|
||||
import io.papermc.paperweight.tasks.GenerateMappings
|
||||
import io.papermc.paperweight.tasks.InspectVanillaJar
|
||||
import io.papermc.paperweight.tasks.Merge
|
||||
import io.papermc.paperweight.tasks.MergeAccessTransforms
|
||||
import io.papermc.paperweight.tasks.PatchMcpCsv
|
||||
import io.papermc.paperweight.tasks.PatchMappings
|
||||
import io.papermc.paperweight.tasks.RemapAccessTransform
|
||||
import io.papermc.paperweight.tasks.RemapJar
|
||||
import io.papermc.paperweight.tasks.RemapSpigotAt
|
||||
import io.papermc.paperweight.tasks.RemapVanillaJarSpigot
|
||||
import io.papermc.paperweight.tasks.RunForgeFlower
|
||||
import io.papermc.paperweight.tasks.RunMcInjector
|
||||
import io.papermc.paperweight.tasks.RunSpecialSource
|
||||
import io.papermc.paperweight.tasks.SetupMcLibraries
|
||||
import io.papermc.paperweight.tasks.WriteLibrariesFile
|
||||
import io.papermc.paperweight.tasks.patchremap.ApplyAccessTransform
|
||||
|
@ -100,11 +97,20 @@ class Paperweight : Plugin<Project> {
|
|||
// Make sure the submodules are initialized
|
||||
Git(target.projectDir)("submodule", "update", "--init").execute()
|
||||
|
||||
target.configurations.create(Constants.YARN_CONFIG)
|
||||
target.configurations.create(Constants.REMAPPER_CONFIG)
|
||||
|
||||
target.repositories.apply {
|
||||
mavenCentral()
|
||||
// Both of these are needed for Spigot
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
|
||||
maven("https://maven.fabricmc.net/") {
|
||||
content {
|
||||
onlyForConfigurations(Constants.YARN_CONFIG, Constants.REMAPPER_CONFIG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target.createTasks(downloadService)
|
||||
|
@ -120,18 +126,28 @@ class Paperweight : Plugin<Project> {
|
|||
|
||||
createPatchRemapTasks(initialTasks, generalTasks, mcpTasks, spigotTasks)
|
||||
|
||||
val applySourceAt by tasks.registering<ApplySourceAt> {
|
||||
inputZip.set(mcpTasks.applyMcpPatches.flatMap { it.outputZip })
|
||||
vanillaJar.set(generalTasks.downloadServerJar.flatMap { it.outputJar })
|
||||
vanillaRemappedSrgJar.set(mcpTasks.remapVanillaJarSrg.flatMap { it.outputJar })
|
||||
val applyMergedAt by tasks.registering<ApplyAccessTransform> {
|
||||
inputJar.set(mcpTasks.fixJar.flatMap { it.outputJar })
|
||||
atFile.set(spigotTasks.mergeGeneratedAts.flatMap { it.outputFile })
|
||||
}
|
||||
|
||||
val mergeRemappedSources by tasks.registering<Merge> {
|
||||
inputJars.add(spigotTasks.remapSpigotSources.flatMap { it.outputZip })
|
||||
inputJars.add(applySourceAt.flatMap { it.outputZip })
|
||||
val writeLibrariesFile by tasks.registering<WriteLibrariesFile> {
|
||||
libraries.set(mcpTasks.downloadMcLibraries.flatMap { it.outputDir })
|
||||
}
|
||||
|
||||
val decompileVanillaJarYarn by tasks.registering<RunForgeFlower> {
|
||||
executable.set(initialTasks.downloadMcpTools.flatMap { it.forgeFlowerFile })
|
||||
configFile.set(initialTasks.extractMcp.flatMap { it.configFile })
|
||||
|
||||
inputJar.set(applyMergedAt.flatMap { it.outputJar })
|
||||
libraries.set(writeLibrariesFile.flatMap { it.outputFile })
|
||||
}
|
||||
|
||||
// val mergeRemappedSources by tasks.registering<Merge> {
|
||||
// inputJars.add(spigotTasks.remapSpigotSources.flatMap { it.outputZip })
|
||||
// inputJars.add(applySourceAt.flatMap { it.outputZip })
|
||||
// }
|
||||
|
||||
val patchPaperApi by tasks.registering<ApplyGitPatches> {
|
||||
branch.set("HEAD")
|
||||
upstreamBranch.set("upstream")
|
||||
|
@ -144,8 +160,11 @@ class Paperweight : Plugin<Project> {
|
|||
|
||||
val patchPaperServer by tasks.registering<ApplyPaperPatches> {
|
||||
patchDir.set(extension.paper.spigotServerPatchDir)
|
||||
remappedSource.set(mergeRemappedSources.flatMap { it.outputJar })
|
||||
remappedSource.set(spigotTasks.remapSpigotSources.flatMap { it.outputZip })
|
||||
templateGitIgnore.set(layout.projectDirectory.file(".gitignore"))
|
||||
sourceMcDevJar.set(decompileVanillaJarYarn.flatMap { it.outputJar })
|
||||
mcLibrariesDir.set(mcpTasks.downloadMcLibraries.flatMap { it.outputDir }.get())
|
||||
libraryImports.set(extension.paper.libraryClassImports)
|
||||
|
||||
outputDir.set(extension.paper.paperServerDir)
|
||||
}
|
||||
|
@ -171,6 +190,7 @@ class Paperweight : Plugin<Project> {
|
|||
// Shared task containers
|
||||
data class InitialTasks(
|
||||
val setupMcLibraries: TaskProvider<SetupMcLibraries>,
|
||||
val downloadMappings: TaskProvider<DownloadTask>,
|
||||
val extractMcp: Provider<ExtractMcp>,
|
||||
val mcpMappings: Provider<ExtractMappings>,
|
||||
val downloadMcpTools: TaskProvider<DownloadMcpTools>
|
||||
|
@ -183,14 +203,13 @@ class Paperweight : Plugin<Project> {
|
|||
)
|
||||
|
||||
data class McpTasks(
|
||||
val generateSrgs: TaskProvider<GenerateSrgs>,
|
||||
val remapVanillaJarSrg: TaskProvider<RunSpecialSource>,
|
||||
val downloadMcLibraries: TaskProvider<DownloadMcLibraries>,
|
||||
val applyMcpPatches: TaskProvider<ApplyMcpPatches>
|
||||
val generateMappings: TaskProvider<GenerateMappings>,
|
||||
val fixJar: TaskProvider<FixJar>,
|
||||
val downloadMcLibraries: TaskProvider<DownloadMcLibraries>
|
||||
)
|
||||
|
||||
data class SpigotTasks(
|
||||
val generateSpigotSrgs: TaskProvider<GenerateSpigotSrgs>,
|
||||
val patchMappings: TaskProvider<PatchMappings>,
|
||||
val decompileVanillaJarSpigot: TaskProvider<DecompileVanillaJar>,
|
||||
val patchSpigotApi: TaskProvider<ApplyGitPatches>,
|
||||
val patchSpigotServer: TaskProvider<ApplyGitPatches>,
|
||||
|
@ -231,6 +250,15 @@ class Paperweight : Plugin<Project> {
|
|||
outputFile.set(cache.resolve(Constants.MC_LIBRARIES))
|
||||
}
|
||||
|
||||
val downloadMappings by tasks.registering<DownloadTask> {
|
||||
url.set(versionManifest.map { version ->
|
||||
version["downloads"]["server_mappings"]["url"].string
|
||||
})
|
||||
outputFile.set(cache.resolve(Constants.SERVER_MAPPINGS))
|
||||
|
||||
downloader.set(downloadService)
|
||||
}
|
||||
|
||||
val downloadMcpFiles by tasks.registering<DownloadMcpFiles> {
|
||||
mcpMinecraftVersion.set(extension.mcpMinecraftVersion)
|
||||
mcpConfigVersion.set(extension.mcpConfigVersion)
|
||||
|
@ -265,6 +293,7 @@ class Paperweight : Plugin<Project> {
|
|||
|
||||
return InitialTasks(
|
||||
setupMcLibraries,
|
||||
downloadMappings,
|
||||
extractMcpConfig,
|
||||
extractMcpMappings,
|
||||
downloadMcpTools
|
||||
|
@ -298,55 +327,57 @@ class Paperweight : Plugin<Project> {
|
|||
): McpTasks {
|
||||
val filterVanillaJar: TaskProvider<Filter> = generalTasks.filterVanillaJar
|
||||
val cache: File = layout.cache
|
||||
val extension: PaperweightExtension = ext
|
||||
|
||||
val mcpRewrites by tasks.registering<PatchMcpCsv> {
|
||||
fieldsCsv.set(initialTasks.mcpMappings.flatMap { it.fieldsCsv })
|
||||
methodsCsv.set(initialTasks.mcpMappings.flatMap { it.methodsCsv })
|
||||
paramsCsv.set(initialTasks.mcpMappings.flatMap { it.paramsCsv })
|
||||
changesFile.set(extension.paper.mcpRewritesFile)
|
||||
|
||||
paperFieldCsv.set(cache.resolve(Constants.PAPER_FIELDS_CSV))
|
||||
paperMethodCsv.set(cache.resolve(Constants.PAPER_METHODS_CSV))
|
||||
paperParamCsv.set(cache.resolve(Constants.PAPER_PARAMS_CSV))
|
||||
}
|
||||
|
||||
val generateSrgs by tasks.registering<GenerateSrgs> {
|
||||
inSrg.set(initialTasks.extractMcp.flatMap { it.mappings })
|
||||
|
||||
methodsCsv.set(mcpRewrites.flatMap { it.paperMethodCsv })
|
||||
fieldsCsv.set(mcpRewrites.flatMap { it.paperFieldCsv })
|
||||
extraNotchSrgMappings.set(extension.paper.extraNotchSrgMappings)
|
||||
// val mcpRewrites by tasks.registering<PatchMcpCsv> {
|
||||
// fieldsCsv.set(initialTasks.mcpMappings.flatMap { it.fieldsCsv })
|
||||
// methodsCsv.set(initialTasks.mcpMappings.flatMap { it.methodsCsv })
|
||||
// paramsCsv.set(initialTasks.mcpMappings.flatMap { it.paramsCsv })
|
||||
// changesFile.set(extension.paper.mcpRewritesFile)
|
||||
//
|
||||
// paperFieldCsv.set(cache.resolve(Constants.PAPER_FIELDS_CSV))
|
||||
// paperMethodCsv.set(cache.resolve(Constants.PAPER_METHODS_CSV))
|
||||
// paperParamCsv.set(cache.resolve(Constants.PAPER_PARAMS_CSV))
|
||||
// }
|
||||
|
||||
val generateMappings by tasks.registering<GenerateMappings> {
|
||||
vanillaJar.set(generalTasks.filterVanillaJar.flatMap { it.outputJar })
|
||||
|
||||
notchToSrg.set(cache.resolve(Constants.NOTCH_TO_SRG))
|
||||
notchToMcp.set(cache.resolve(Constants.NOTCH_TO_MCP))
|
||||
srgToNotch.set(cache.resolve(Constants.SRG_TO_NOTCH))
|
||||
srgToMcp.set(cache.resolve(Constants.SRG_TO_MCP))
|
||||
mcpToNotch.set(cache.resolve(Constants.MCP_TO_NOTCH))
|
||||
mcpToSrg.set(cache.resolve(Constants.MCP_TO_SRG))
|
||||
vanillaMappings.set(initialTasks.downloadMappings.flatMap { it.outputFile })
|
||||
yarnMappings.fileProvider(configurations.named(Constants.YARN_CONFIG).map { it.singleFile })
|
||||
|
||||
outputMappings.set(cache.resolve(Constants.SRG_DIR).resolve("merged.tiny"))
|
||||
}
|
||||
|
||||
val remapVanillaJarSrg by tasks.registering<RunSpecialSource> {
|
||||
val remapJar by tasks.registering<RemapJar> {
|
||||
inputJar.set(filterVanillaJar.flatMap { it.outputJar })
|
||||
mappings.set(generateSrgs.flatMap { it.notchToSrg })
|
||||
|
||||
executable.set(initialTasks.downloadMcpTools.flatMap { it.specialSourceFile })
|
||||
configFile.set(initialTasks.extractMcp.flatMap { it.configFile })
|
||||
mappingsFile.set(generateMappings.flatMap { it.outputMappings })
|
||||
remapper.fileProvider(configurations.named(Constants.REMAPPER_CONFIG).map { it.singleFile })
|
||||
}
|
||||
|
||||
val injectVanillaJarSrg by tasks.registering<RunMcInjector> {
|
||||
executable.set(initialTasks.downloadMcpTools.flatMap { it.mcInjectorFile })
|
||||
configFile.set(initialTasks.extractMcp.flatMap { it.configFile })
|
||||
|
||||
exceptions.set(initialTasks.extractMcp.flatMap { it.exceptions })
|
||||
access.set(initialTasks.extractMcp.flatMap { it.access })
|
||||
constructors.set(initialTasks.extractMcp.flatMap { it.constructors })
|
||||
|
||||
inputJar.set(remapVanillaJarSrg.flatMap { it.outputJar })
|
||||
val fixJar by tasks.registering<FixJar> {
|
||||
// executable.set(initialTasks.downloadMcpTools.flatMap { it.mcInjectorFile })
|
||||
inputJar.set(remapJar.flatMap { it.outputJar })
|
||||
}
|
||||
|
||||
// val remapVanillaJarSrg by tasks.registering<RunSpecialSource> {
|
||||
// inputJar.set(filterVanillaJar.flatMap { it.outputJar })
|
||||
// mappings.set(generateSrgs.flatMap { it.notchToSrg })
|
||||
//
|
||||
// executable.set(initialTasks.downloadMcpTools.flatMap { it.specialSourceFile })
|
||||
// configFile.set(initialTasks.extractMcp.flatMap { it.configFile })
|
||||
// }
|
||||
//
|
||||
// val injectVanillaJarSrg by tasks.registering<RunMcInjector> {
|
||||
// executable.set(initialTasks.downloadMcpTools.flatMap { it.mcInjectorFile })
|
||||
// configFile.set(initialTasks.extractMcp.flatMap { it.configFile })
|
||||
//
|
||||
// exceptions.set(initialTasks.extractMcp.flatMap { it.exceptions })
|
||||
// access.set(initialTasks.extractMcp.flatMap { it.access })
|
||||
// constructors.set(initialTasks.extractMcp.flatMap { it.constructors })
|
||||
//
|
||||
// inputJar.set(remapVanillaJarSrg.flatMap { it.outputJar })
|
||||
// }
|
||||
|
||||
val downloadMcLibraries by tasks.registering<DownloadMcLibraries> {
|
||||
mcLibrariesFile.set(initialTasks.setupMcLibraries.flatMap { it.outputFile })
|
||||
mcRepo.set(Constants.MC_LIBRARY_URL)
|
||||
|
@ -354,26 +385,14 @@ class Paperweight : Plugin<Project> {
|
|||
|
||||
downloader.set(downloadService)
|
||||
}
|
||||
//
|
||||
// val applyMcpPatches by tasks.registering<ApplyMcpPatches> {
|
||||
// inputZip.set(decompileVanillaJarSrg.flatMap { it.outputJar })
|
||||
// serverPatchDir.set(initialTasks.extractMcp.flatMap { it.patchDir })
|
||||
// configFile.set(cache.resolve(Constants.MCP_CONFIG_JSON))
|
||||
// }
|
||||
|
||||
val writeLibrariesFile by tasks.registering<WriteLibrariesFile> {
|
||||
libraries.set(downloadMcLibraries.flatMap { it.outputDir })
|
||||
}
|
||||
|
||||
val decompileVanillaJarSrg by tasks.registering<RunForgeFlower> {
|
||||
executable.set(initialTasks.downloadMcpTools.flatMap { it.forgeFlowerFile })
|
||||
configFile.set(initialTasks.extractMcp.flatMap { it.configFile })
|
||||
|
||||
inputJar.set(injectVanillaJarSrg.flatMap { it.outputJar })
|
||||
libraries.set(writeLibrariesFile.flatMap { it.outputFile })
|
||||
}
|
||||
|
||||
val applyMcpPatches by tasks.registering<ApplyMcpPatches> {
|
||||
inputZip.set(decompileVanillaJarSrg.flatMap { it.outputJar })
|
||||
serverPatchDir.set(initialTasks.extractMcp.flatMap { it.patchDir })
|
||||
configFile.set(cache.resolve(Constants.MCP_CONFIG_JSON))
|
||||
}
|
||||
|
||||
return McpTasks(generateSrgs, remapVanillaJarSrg, downloadMcLibraries, applyMcpPatches)
|
||||
return McpTasks(generateMappings, fixJar, downloadMcLibraries)
|
||||
}
|
||||
|
||||
private fun Project.createSpigotTasks(
|
||||
|
@ -386,35 +405,38 @@ class Paperweight : Plugin<Project> {
|
|||
val extension: PaperweightExtension = ext
|
||||
|
||||
val (buildDataInfo, downloadServerJar, filterVanillaJar) = generalTasks
|
||||
val (generateSrgs, _, _) = mcpTasks
|
||||
val (generateMappings, _, _) = mcpTasks
|
||||
|
||||
val addMissingSpigotClassMappings by tasks.registering<AddMissingSpigotClassMappings> {
|
||||
val addAdditionalSpigotMappings by tasks.registering<AddAdditionalSpigotMappings> {
|
||||
classSrg.set(extension.craftBukkit.mappingsDir.file(buildDataInfo.map { it.classMappings }))
|
||||
memberSrg.set(extension.craftBukkit.mappingsDir.file(buildDataInfo.map { it.memberMappings }))
|
||||
missingClassEntriesSrg.set(extension.paper.missingClassEntriesSrgFile)
|
||||
missingMemberEntriesSrg.set(extension.paper.missingMemberEntriesSrgFile)
|
||||
additionalClassEntriesSrg.set(extension.paper.additionalSpigotClassMappings)
|
||||
additionalMemberEntriesSrg.set(extension.paper.additionalSpigotMemberMappings)
|
||||
}
|
||||
|
||||
val inspectVanillaJar by tasks.registering<InspectVanillaJar> {
|
||||
inputJar.set(downloadServerJar.flatMap { it.outputJar })
|
||||
}
|
||||
|
||||
val generateSpigotSrgs by tasks.registering<GenerateSpigotSrgs> {
|
||||
notchToSrg.set(generateSrgs.flatMap { it.notchToSrg })
|
||||
srgToMcp.set(generateSrgs.flatMap { it.srgToMcp })
|
||||
classMappings.set(addMissingSpigotClassMappings.flatMap { it.outputClassSrg })
|
||||
memberMappings.set(addMissingSpigotClassMappings.flatMap { it.outputMemberSrg })
|
||||
val generateSpigotMappings by tasks.registering<GenerateSpigotMappings> {
|
||||
classMappings.set(addAdditionalSpigotMappings.flatMap { it.outputClassSrg })
|
||||
memberMappings.set(addAdditionalSpigotMappings.flatMap { it.outputMemberSrg })
|
||||
packageMappings.set(extension.craftBukkit.mappingsDir.file(buildDataInfo.map { it.packageMappings }))
|
||||
extraSpigotSrgMappings.set(extension.paper.extraSpigotSrgMappings)
|
||||
loggerFields.set(inspectVanillaJar.flatMap { it.outputFile })
|
||||
vanillaJar.set(filterVanillaJar.flatMap { it.outputJar })
|
||||
|
||||
spigotToSrg.set(cache.resolve(Constants.SPIGOT_TO_SRG))
|
||||
spigotToMcp.set(cache.resolve(Constants.SPIGOT_TO_MCP))
|
||||
spigotToNotch.set(cache.resolve(Constants.SPIGOT_TO_NOTCH))
|
||||
srgToSpigot.set(cache.resolve(Constants.SRG_TO_SPIGOT))
|
||||
mcpToSpigot.set(cache.resolve(Constants.MCP_TO_SPIGOT))
|
||||
notchToSpigot.set(cache.resolve(Constants.NOTCH_TO_SPIGOT))
|
||||
loggerFields.set(inspectVanillaJar.flatMap { it.loggerFile })
|
||||
paramIndexes.set(inspectVanillaJar.flatMap { it.paramIndexes })
|
||||
syntheticMethods.set(inspectVanillaJar.flatMap { it.syntheticMethods })
|
||||
|
||||
sourceMappings.set(generateMappings.flatMap { it.outputMappings })
|
||||
|
||||
outputMappings.set(cache.resolve(Constants.SRG_DIR).resolve("spigot-named.tiny"))
|
||||
}
|
||||
|
||||
val patchMappings by tasks.registering<PatchMappings> {
|
||||
inputMappings.set(generateSpigotMappings.flatMap { it.outputMappings })
|
||||
patchMappings.set(extension.paper.mappingsPatch)
|
||||
|
||||
outputMappings.set(cache.resolve(Constants.SRG_DIR).resolve("spigot-named-patched.tiny"))
|
||||
}
|
||||
|
||||
val remapVanillaJarSpigot by tasks.registering<RemapVanillaJarSpigot> {
|
||||
|
@ -487,14 +509,14 @@ class Paperweight : Plugin<Project> {
|
|||
|
||||
val remapSpigotAt by tasks.registering<RemapSpigotAt> {
|
||||
inputJar.set(remapVanillaJarSpigot.flatMap { it.outputJar })
|
||||
mapping.set(generateSpigotSrgs.flatMap { it.spigotToSrg })
|
||||
mapping.set(patchMappings.flatMap { it.outputMappings })
|
||||
spigotAt.set(extension.craftBukkit.atFile)
|
||||
}
|
||||
|
||||
val remapSpigotSources by tasks.registering<RemapSources> {
|
||||
spigotServerDir.set(patchSpigotServer.flatMap { it.outputDir })
|
||||
spigotApiDir.set(patchSpigotApi.flatMap { it.outputDir })
|
||||
mappings.set(generateSpigotSrgs.flatMap { it.spigotToSrg })
|
||||
mappings.set(patchMappings.flatMap { it.outputMappings })
|
||||
vanillaJar.set(downloadServerJar.flatMap { it.outputJar })
|
||||
vanillaRemappedSpigotJar.set(removeSpigotExcludes.flatMap { it.outputZip })
|
||||
spigotDeps.set(downloadSpigotDependencies.flatMap { it.outputDir })
|
||||
|
@ -503,7 +525,7 @@ class Paperweight : Plugin<Project> {
|
|||
|
||||
val remapGeneratedAt by tasks.registering<RemapAccessTransform> {
|
||||
inputFile.set(remapSpigotSources.flatMap { it.generatedAt })
|
||||
mappings.set(generateSpigotSrgs.flatMap { it.spigotToSrg })
|
||||
mappings.set(patchMappings.flatMap { it.outputMappings })
|
||||
}
|
||||
|
||||
val mergeGeneratedAts by tasks.registering<MergeAccessTransforms> {
|
||||
|
@ -512,7 +534,7 @@ class Paperweight : Plugin<Project> {
|
|||
}
|
||||
|
||||
return SpigotTasks(
|
||||
generateSpigotSrgs,
|
||||
patchMappings,
|
||||
decompileVanillaJarSpigot,
|
||||
patchSpigotApi,
|
||||
patchSpigotServer,
|
||||
|
@ -540,7 +562,7 @@ class Paperweight : Plugin<Project> {
|
|||
*/
|
||||
|
||||
val applyVanillaSrgAt by tasks.registering<ApplyAccessTransform> {
|
||||
inputJar.set(mcpTasks.remapVanillaJarSrg.flatMap { it.outputJar })
|
||||
inputJar.set(mcpTasks.fixJar.flatMap { it.outputJar })
|
||||
atFile.set(spigotTasks.mergeGeneratedAts.flatMap { it.outputFile })
|
||||
}
|
||||
|
||||
|
@ -564,7 +586,7 @@ class Paperweight : Plugin<Project> {
|
|||
// sourceJar.set(spigotTasks.remapSpigotSources.flatMap { it.outputZip }.get())
|
||||
apiPatchDir.set(extension.paper.spigotApiPatchDir)
|
||||
|
||||
mappingsFile.set(spigotTasks.generateSpigotSrgs.flatMap { it.spigotToSrg }.get())
|
||||
mappingsFile.set(spigotTasks.patchMappings.flatMap { it.outputMappings }.get())
|
||||
|
||||
// Pull in as many jars as possible to reduce the possibility of type bindings not resolving
|
||||
classpathJars.add(generalTasks.downloadServerJar.flatMap { it.outputJar }.get())
|
||||
|
|
|
@ -39,19 +39,15 @@ open class PaperExtension(objects: ObjectFactory, layout: ProjectLayout) {
|
|||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
val mcpDir: DirectoryProperty = objects.dirWithDefault(layout, "mcp")
|
||||
val mcpRewritesFile: RegularFileProperty = objects.fileFrom(mcpDir, "mcp-rewrites.txt")
|
||||
val missingClassEntriesSrgFile: RegularFileProperty = objects.fileFrom(mcpDir, "missing-spigot-class-mappings.csrg")
|
||||
val missingMemberEntriesSrgFile: RegularFileProperty = objects.fileFrom(mcpDir, "missing-spigot-member-mappings.csrg")
|
||||
val extraNotchSrgMappings: RegularFileProperty = objects.fileFrom(mcpDir, "extra-notch-srg.tsrg")
|
||||
val extraSpigotSrgMappings: RegularFileProperty = objects.fileFrom(mcpDir, "extra-spigot-srg.tsrg")
|
||||
val additionalSpigotClassMappings: RegularFileProperty = objects.fileProperty()
|
||||
val additionalSpigotMemberMappings: RegularFileProperty = objects.fileProperty()
|
||||
val libraryClassImports: RegularFileProperty = objects.fileFrom(mcpDir, "library-imports.txt")
|
||||
val mappingsPatch: RegularFileProperty = objects.fileProperty()
|
||||
|
||||
init {
|
||||
spigotApiPatchDir.disallowUnsafeRead()
|
||||
spigotServerPatchDir.disallowUnsafeRead()
|
||||
paperApiDir.disallowUnsafeRead()
|
||||
paperServerDir.disallowUnsafeRead()
|
||||
|
||||
mcpRewritesFile.disallowUnsafeRead()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.gradle.api.tasks.Optional
|
|||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class AddMissingSpigotClassMappings : BaseTask() {
|
||||
abstract class AddAdditionalSpigotMappings : BaseTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val classSrg: RegularFileProperty
|
||||
|
@ -40,10 +40,10 @@ abstract class AddMissingSpigotClassMappings : BaseTask() {
|
|||
abstract val memberSrg: RegularFileProperty
|
||||
@get:Optional
|
||||
@get:InputFile
|
||||
abstract val missingClassEntriesSrg: RegularFileProperty
|
||||
abstract val additionalClassEntriesSrg: RegularFileProperty
|
||||
@get:Optional
|
||||
@get:InputFile
|
||||
abstract val missingMemberEntriesSrg: RegularFileProperty
|
||||
abstract val additionalMemberEntriesSrg: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputClassSrg: RegularFileProperty
|
||||
|
@ -57,8 +57,8 @@ abstract class AddMissingSpigotClassMappings : BaseTask() {
|
|||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
addLines(classSrg.file, missingClassEntriesSrg.fileOrNull, outputClassSrg.file)
|
||||
addLines(memberSrg.file, missingMemberEntriesSrg.fileOrNull, outputMemberSrg.file)
|
||||
addLines(classSrg.file, additionalClassEntriesSrg.fileOrNull, outputClassSrg.file)
|
||||
addLines(memberSrg.file, additionalMemberEntriesSrg.fileOrNull, outputMemberSrg.file)
|
||||
}
|
||||
|
||||
private fun addLines(inFile: File, appendFile: File?, outputFile: File) {
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* paperweight is a Gradle plugin for the PaperMC project. It uses
|
||||
* some code and systems originally from ForgeGradle.
|
||||
*
|
||||
* Copyright (C) 2020 Kyle Wood
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Git
|
||||
import java.io.File
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.InputFile
|
||||
|
||||
abstract class ApplyMcpPatches : ZippedTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
abstract val serverPatchDir: DirectoryProperty
|
||||
@get:InputFile
|
||||
abstract val configFile: RegularFileProperty
|
||||
|
||||
override fun run(rootDir: File) {
|
||||
val git = Git(rootDir)
|
||||
|
||||
val extension = ".java.patch"
|
||||
objects.fileTree().from(serverPatchDir).matching {
|
||||
include("**/*$extension")
|
||||
}.forEach { patch ->
|
||||
git("apply", "--ignore-whitespace", patch.absolutePath).executeSilently()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Git
|
||||
import io.papermc.paperweight.util.McDev
|
||||
import io.papermc.paperweight.util.file
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
|
@ -39,6 +40,12 @@ abstract class ApplyPaperPatches : ControllableOutputTask() {
|
|||
abstract val remappedSource: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val templateGitIgnore: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val sourceMcDevJar: RegularFileProperty
|
||||
@get:InputDirectory
|
||||
abstract val mcLibrariesDir: DirectoryProperty
|
||||
@get:InputFile
|
||||
abstract val libraryImports: RegularFileProperty
|
||||
|
||||
@get:OutputDirectory
|
||||
abstract val outputDir: DirectoryProperty
|
||||
|
@ -78,6 +85,9 @@ abstract class ApplyPaperPatches : ControllableOutputTask() {
|
|||
into(sourceDir)
|
||||
}
|
||||
|
||||
val patches = patchDir.file.listFiles { _, name -> name.endsWith(".patch") } ?: emptyArray()
|
||||
McDev.importMcDev(patches, sourceMcDevJar.file, libraryImports.file, mcLibrariesDir.file, sourceDir)
|
||||
|
||||
templateGitIgnore.file.copyTo(outputFile.resolve(".gitignore"))
|
||||
|
||||
git("add", ".gitignore", ".").executeSilently()
|
||||
|
|
154
src/main/kotlin/tasks/FixJar.kt
Normal file
154
src/main/kotlin/tasks/FixJar.kt
Normal file
|
@ -0,0 +1,154 @@
|
|||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.AsmUtil
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.util.jar.JarFile
|
||||
import java.util.jar.JarOutputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.Type
|
||||
import org.objectweb.asm.tree.AnnotationNode
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
abstract class FixJar : BaseTask(), AsmUtil {
|
||||
|
||||
@get:InputFile
|
||||
abstract val inputJar: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputJar: RegularFileProperty
|
||||
|
||||
override fun init() {
|
||||
outputJar.convention(defaultOutput())
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
JarOutputStream(outputJar.file.outputStream()).use { out ->
|
||||
JarFile(inputJar.file).use { jarFile ->
|
||||
for (entry in jarFile.entries()) {
|
||||
if (!entry.name.endsWith(".class")) {
|
||||
out.putNextEntry(entry)
|
||||
try {
|
||||
jarFile.getInputStream(entry).copyTo(out)
|
||||
} finally {
|
||||
out.closeEntry()
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
val classData = if (entry.size != -1L) {
|
||||
ByteArray(entry.size.toInt()).also { data ->
|
||||
jarFile.getInputStream(entry).readNBytes(data, 0, data.size)
|
||||
}
|
||||
} else {
|
||||
jarFile.getInputStream(entry).readAllBytes()
|
||||
}
|
||||
|
||||
try {
|
||||
val node = ClassNode(Opcodes.ASM9)
|
||||
var visitor: ClassVisitor = node
|
||||
visitor = ParameterAnnotationFixer(node, visitor)
|
||||
|
||||
val reader = ClassReader(classData)
|
||||
reader.accept(visitor, 0)
|
||||
|
||||
val writer = ClassWriter(0)
|
||||
node.accept(writer)
|
||||
|
||||
out.putNextEntry(ZipEntry(entry.name))
|
||||
out.write(writer.toByteArray())
|
||||
out.flush()
|
||||
} finally {
|
||||
out.closeEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ParameterAnnotationFixer(
|
||||
private val node: ClassNode,
|
||||
classVisitor: ClassVisitor?
|
||||
) : ClassVisitor(Opcodes.ASM9, classVisitor), AsmUtil {
|
||||
|
||||
override fun visitEnd() {
|
||||
super.visitEnd()
|
||||
|
||||
val expected = expectedSyntheticParams() ?: return
|
||||
|
||||
for (method in node.methods) {
|
||||
if (method.name == "<init>") {
|
||||
processConstructor(method, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun expectedSyntheticParams(): List<Type>? {
|
||||
if (Opcodes.ACC_ENUM in node.access) {
|
||||
return listOf(Type.getObjectType("java/lang/String"), Type.INT_TYPE)
|
||||
}
|
||||
|
||||
val innerNode = node.innerClasses.firstOrNull { it.name == node.name } ?: return null
|
||||
if (innerNode.innerName == null || (Opcodes.ACC_STATIC or Opcodes.ACC_INTERFACE) in innerNode.access) {
|
||||
return null
|
||||
}
|
||||
|
||||
return listOf(Type.getObjectType(innerNode.outerName))
|
||||
}
|
||||
|
||||
private fun processConstructor(method: MethodNode, synthParams: List<Type>) {
|
||||
val params = Type.getArgumentTypes(method.desc).asList()
|
||||
|
||||
if (!params.beginsWith(synthParams)) {
|
||||
return
|
||||
}
|
||||
|
||||
method.visibleParameterAnnotations = process(params.size, synthParams.size, method.visibleParameterAnnotations)
|
||||
method.invisibleParameterAnnotations = process(params.size, synthParams.size, method.invisibleParameterAnnotations)
|
||||
|
||||
method.visibleParameterAnnotations?.let {
|
||||
method.visibleAnnotableParameterCount = it.size
|
||||
}
|
||||
method.invisibleParameterAnnotations?.let {
|
||||
method.invisibleAnnotableParameterCount = it.size
|
||||
}
|
||||
}
|
||||
|
||||
private fun process(
|
||||
paramCount: Int,
|
||||
synthCount: Int,
|
||||
annotations: Array<List<AnnotationNode>>?
|
||||
): Array<List<AnnotationNode>>? {
|
||||
if (annotations == null) {
|
||||
return null
|
||||
}
|
||||
if (paramCount == annotations.size) {
|
||||
return annotations.copyOfRange(synthCount, paramCount)
|
||||
}
|
||||
return annotations
|
||||
}
|
||||
|
||||
private fun <T> List<T>.beginsWith(other: List<T>): Boolean {
|
||||
if (this.size < other.size) {
|
||||
return false
|
||||
}
|
||||
for (i in other.indices) {
|
||||
if (this[i] != other[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
240
src/main/kotlin/tasks/GenerateMappings.kt
Normal file
240
src/main/kotlin/tasks/GenerateMappings.kt
Normal file
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* paperweight is a Gradle plugin for the PaperMC project. It uses
|
||||
* some code and systems originally from ForgeGradle.
|
||||
*
|
||||
* Copyright (C) 2020 Kyle Wood
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.ensureParentExists
|
||||
import io.papermc.paperweight.util.path
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.cadixdev.atlas.Atlas
|
||||
import org.cadixdev.bombe.asm.jar.JarEntryRemappingTransformer
|
||||
import org.cadixdev.lorenz.MappingSet
|
||||
import org.cadixdev.lorenz.asm.LorenzRemapper
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
import org.cadixdev.lorenz.merge.FieldMergeStrategy
|
||||
import org.cadixdev.lorenz.merge.MappingSetMerger
|
||||
import org.cadixdev.lorenz.merge.MappingSetMergerHandler
|
||||
import org.cadixdev.lorenz.merge.MergeConfig
|
||||
import org.cadixdev.lorenz.merge.MergeContext
|
||||
import org.cadixdev.lorenz.merge.MergeResult
|
||||
import org.cadixdev.lorenz.model.ClassMapping
|
||||
import org.cadixdev.lorenz.model.FieldMapping
|
||||
import org.cadixdev.lorenz.model.InnerClassMapping
|
||||
import org.cadixdev.lorenz.model.MethodMapping
|
||||
import org.cadixdev.lorenz.model.MethodParameterMapping
|
||||
import org.cadixdev.lorenz.model.TopLevelClassMapping
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class GenerateMappings : DefaultTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val vanillaJar: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val vanillaMappings: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val yarnMappings: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputMappings: RegularFileProperty
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val vanillaMappings = MappingFormats.byId("proguard").createReader(vanillaMappings.path).use { it.read() }.reverse()
|
||||
|
||||
val yarnMappings = FileSystems.newFileSystem(yarnMappings.path, null).use { fs ->
|
||||
val path = fs.getPath("mappings", "mappings.tiny")
|
||||
TinyMappingFormat.STANDARD.read(path, "official", "named")
|
||||
}
|
||||
|
||||
val merged = MappingSetMerger.create(
|
||||
vanillaMappings,
|
||||
yarnMappings,
|
||||
MergeConfig.builder()
|
||||
.withFieldMergeStrategy(FieldMergeStrategy.STRICT)
|
||||
.withMergeHandler(MergeHandler())
|
||||
.build()
|
||||
).merge()
|
||||
|
||||
// Fill out any missing inheritance info in the mappings
|
||||
val atlasOut = Files.createTempFile("paperweight", "jar")
|
||||
try {
|
||||
Atlas().use { atlas ->
|
||||
atlas.install { ctx -> JarEntryRemappingTransformer(LorenzRemapper(merged, ctx.inheritanceProvider())) }
|
||||
atlas.run(vanillaJar.path, atlasOut)
|
||||
}
|
||||
} finally {
|
||||
Files.deleteIfExists(atlasOut)
|
||||
}
|
||||
|
||||
ensureParentExists(outputMappings)
|
||||
TinyMappingFormat.STANDARD.write(merged, outputMappings.path, Constants.OBF_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
}
|
||||
|
||||
/*
|
||||
private fun remapAnonymousClasses(mapping: InnerClassMapping, target: ClassMapping<*, *>) {
|
||||
val newMapping = target.createInnerClassMapping(mapping.obfuscatedName, mapping.deobfuscatedName)
|
||||
remapMembers(mapping, newMapping)
|
||||
}
|
||||
|
||||
private fun <T : ClassMapping<*, *>> remapMembers(mapping: T, newMapping: T) {
|
||||
for (fieldMapping in mapping.fieldMappings) {
|
||||
newMapping.createFieldMapping(fieldMapping.obfuscatedName, fieldMapping.deobfuscatedName)
|
||||
}
|
||||
for (methodMapping in mapping.methodMappings) {
|
||||
newMapping.createMethodMapping(methodMapping.signature, methodMapping.deobfuscatedName)
|
||||
}
|
||||
for (innerClassMapping in mapping.innerClassMappings) {
|
||||
remapAnonymousClasses(innerClassMapping, newMapping)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
private fun mergeClass(vanillaMapping: ClassMapping<*, *>, yarnMapping: ClassMapping<*, *>) {
|
||||
for (vanillaMethod in vanillaMapping.methodMappings) {
|
||||
val yarnMethod = yarnMapping.getMethodMapping(vanillaMethod.signature).orNull ?: continue
|
||||
for (yarnParam in yarnMethod.parameterMappings) {
|
||||
vanillaMethod.getOrCreateParameterMapping(yarnParam.index).deobfuscatedName = yarnParam.deobfuscatedName
|
||||
}
|
||||
}
|
||||
|
||||
for (vanillaClass in vanillaMapping.innerClassMappings) {
|
||||
val yarnClass = yarnMapping.getInnerClassMapping(vanillaClass.obfuscatedName).orNull ?: continue
|
||||
mergeClass(vanillaClass, yarnClass)
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
class MergeHandler : MappingSetMergerHandler {
|
||||
|
||||
override fun mergeTopLevelClassMappings(
|
||||
left: TopLevelClassMapping,
|
||||
right: TopLevelClassMapping,
|
||||
target: MappingSet,
|
||||
context: MergeContext
|
||||
): MergeResult<TopLevelClassMapping?> {
|
||||
throw IllegalStateException("Unexpectedly merged class: ${left.fullObfuscatedName}")
|
||||
}
|
||||
override fun mergeDuplicateTopLevelClassMappings(
|
||||
left: TopLevelClassMapping,
|
||||
right: TopLevelClassMapping,
|
||||
rightContinuation: TopLevelClassMapping?,
|
||||
target: MappingSet,
|
||||
context: MergeContext
|
||||
): MergeResult<TopLevelClassMapping?> {
|
||||
return MergeResult(
|
||||
target.createTopLevelClassMapping(left.obfuscatedName, left.deobfuscatedName),
|
||||
right
|
||||
)
|
||||
}
|
||||
|
||||
override fun mergeInnerClassMappings(
|
||||
left: InnerClassMapping,
|
||||
right: InnerClassMapping,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<InnerClassMapping?> {
|
||||
throw IllegalStateException("Unexpectedly merged class: ${left.fullObfuscatedName}")
|
||||
}
|
||||
override fun mergeDuplicateInnerClassMappings(
|
||||
left: InnerClassMapping,
|
||||
right: InnerClassMapping,
|
||||
rightContinuation: InnerClassMapping?,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<InnerClassMapping?> {
|
||||
return MergeResult(
|
||||
target.createInnerClassMapping(left.obfuscatedName, left.deobfuscatedName),
|
||||
right
|
||||
)
|
||||
}
|
||||
|
||||
override fun mergeFieldMappings(
|
||||
left: FieldMapping,
|
||||
strictRight: FieldMapping?,
|
||||
looseRight: FieldMapping?,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): FieldMapping? {
|
||||
throw IllegalStateException("Unexpectedly merged field: ${left.fullObfuscatedName}")
|
||||
}
|
||||
override fun mergeDuplicateFieldMappings(
|
||||
left: FieldMapping,
|
||||
strictRightDuplicate: FieldMapping?,
|
||||
looseRightDuplicate: FieldMapping?,
|
||||
strictRightContinuation: FieldMapping?,
|
||||
looseRightContinuation: FieldMapping?,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): FieldMapping? {
|
||||
return target.createFieldMapping(left.signature, left.deobfuscatedName)
|
||||
}
|
||||
override fun addLeftFieldMapping(
|
||||
left: FieldMapping,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): FieldMapping? {
|
||||
return target.createFieldMapping(left.signature, left.deobfuscatedName)
|
||||
}
|
||||
|
||||
override fun mergeMethodMappings(
|
||||
left: MethodMapping,
|
||||
standardRight: MethodMapping?,
|
||||
wiggledRight: MethodMapping?,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<MethodMapping?> {
|
||||
throw IllegalStateException("Unexpectedly merged method: ${left.fullObfuscatedName}")
|
||||
}
|
||||
override fun mergeDuplicateMethodMappings(
|
||||
left: MethodMapping,
|
||||
standardRightDuplicate: MethodMapping?,
|
||||
wiggledRightDuplicate: MethodMapping?,
|
||||
standardRightContinuation: MethodMapping?,
|
||||
wiggledRightContinuation: MethodMapping?,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<MethodMapping?> {
|
||||
return MergeResult(
|
||||
target.createMethodMapping(left.signature, left.deobfuscatedName),
|
||||
listOfNotNull(standardRightDuplicate, wiggledRightDuplicate)
|
||||
)
|
||||
}
|
||||
|
||||
override fun mergeParameterMappings(
|
||||
left: MethodParameterMapping,
|
||||
right: MethodParameterMapping,
|
||||
target: MethodMapping,
|
||||
context: MergeContext
|
||||
): MethodParameterMapping? {
|
||||
throw IllegalStateException("Unexpectedly merged method: ${left.fullObfuscatedName}")
|
||||
}
|
||||
}
|
|
@ -22,15 +22,14 @@
|
|||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.fileOrNull
|
||||
import io.papermc.paperweight.util.orNull
|
||||
import io.papermc.paperweight.util.path
|
||||
import io.papermc.paperweight.util.writeMappings
|
||||
import java.nio.file.Files
|
||||
import org.cadixdev.atlas.Atlas
|
||||
import org.cadixdev.bombe.asm.jar.JarEntryRemappingTransformer
|
||||
import java.util.Optional
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.cadixdev.bombe.type.signature.MethodSignature
|
||||
import org.cadixdev.lorenz.MappingSet
|
||||
import org.cadixdev.lorenz.asm.LorenzRemapper
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
import org.cadixdev.lorenz.merge.MappingSetMerger
|
||||
import org.cadixdev.lorenz.merge.MappingSetMergerHandler
|
||||
|
@ -45,110 +44,184 @@ import org.cadixdev.lorenz.model.TopLevelClassMapping
|
|||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class GenerateSpigotSrgs : DefaultTask() {
|
||||
abstract class GenerateSpigotMappings : DefaultTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val notchToSrg: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val srgToMcp: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val classMappings: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val memberMappings: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val packageMappings: RegularFileProperty
|
||||
@get:Optional
|
||||
@get:InputFile
|
||||
abstract val extraSpigotSrgMappings: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val loggerFields: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val paramIndexes: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val syntheticMethods: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val vanillaJar: RegularFileProperty
|
||||
abstract val sourceMappings: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val spigotToSrg: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val spigotToMcp: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val spigotToNotch: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val srgToSpigot: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val mcpToSpigot: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val notchToSpigot: RegularFileProperty
|
||||
abstract val outputMappings: RegularFileProperty
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val classMappingSet = MappingFormats.CSRG.createReader(classMappings.file.toPath()).use { it.read() }
|
||||
val memberMappingSet = MappingFormats.CSRG.createReader(memberMappings.file.toPath()).use { it.read() }
|
||||
val classMappingSet = MappingFormats.CSRG.createReader(classMappings.path).use { it.read() }
|
||||
val memberMappingSet = MappingFormats.CSRG.createReader(memberMappings.path).use { it.read() }
|
||||
val mergedMappingSet = MappingSetMerger.create(classMappingSet, memberMappingSet).merge()
|
||||
|
||||
for (line in loggerFields.file.readLines(Charsets.UTF_8)) {
|
||||
val (className, fieldName) = line.split(' ')
|
||||
val classMapping = mergedMappingSet.getClassMapping(className).orElse(null) ?: continue
|
||||
classMapping.getOrCreateFieldMapping(fieldName).deobfuscatedName = "LOGGER"
|
||||
classMapping.getOrCreateFieldMapping(fieldName, "Lorg/apache/logging/log4j/Logger;").deobfuscatedName = "LOGGER"
|
||||
}
|
||||
|
||||
// Get the new package name
|
||||
val newPackage = packageMappings.asFile.get().readLines()[0].split(Regex("\\s+"))[1]
|
||||
|
||||
// We'll use notch->srg to pick up any classes spigot doesn't map for the package mapping
|
||||
val notchToSrgSet = MappingFormats.TSRG.createReader(notchToSrg.file.toPath()).use { it.read() }
|
||||
val sourceMappings = TinyMappingFormat.STANDARD.read(sourceMappings.path, Constants.OBF_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
|
||||
val synths = hashMapOf<String, MutableMap<String, MutableMap<String, String>>>()
|
||||
syntheticMethods.file.useLines { lines ->
|
||||
for (line in lines) {
|
||||
val (className, desc, synthName, baseName) = line.split(" ")
|
||||
synths.computeIfAbsent(className) { hashMapOf() }
|
||||
.computeIfAbsent(desc) { hashMapOf() }[baseName] = synthName
|
||||
}
|
||||
}
|
||||
|
||||
val notchToSpigotSet = MappingSetMerger.create(
|
||||
mergedMappingSet,
|
||||
notchToSrgSet,
|
||||
sourceMappings,
|
||||
MergeConfig.builder()
|
||||
.withMergeHandler(SpigotPackageMergerHandler(newPackage))
|
||||
.withMergeHandler(SpigotPackageMergerHandler(newPackage, synths))
|
||||
.build()
|
||||
).merge()
|
||||
|
||||
// TODO Not sure if this is still needed here since it's already ran in GenerateSrgs too now
|
||||
// notch <-> spigot is incomplete here, it would result in inheritance issues to work with this incomplete set.
|
||||
// so we use it once to remap some jar, which fills out the inheritance data
|
||||
// val atlasOut = Files.createTempFile("paperweight", "jar")
|
||||
// try {
|
||||
// Atlas().use { atlas ->
|
||||
// atlas.install { ctx -> JarEntryRemappingTransformer(LorenzRemapper(notchToSpigotSet, ctx.inheritanceProvider())) }
|
||||
// atlas.run(vanillaJar.path, atlasOut)
|
||||
// }
|
||||
// } finally {
|
||||
// Files.deleteIfExists(atlasOut)
|
||||
// }
|
||||
val adjustedSourceMappings = adjustParamIndexes(sourceMappings)
|
||||
|
||||
val srgToMcpSet = MappingFormats.TSRG.createReader(srgToMcp.file.toPath()).use { it.read() }
|
||||
val spigotToNamedSet = MappingSetMerger.create(
|
||||
notchToSpigotSet.reverse(),
|
||||
adjustedSourceMappings
|
||||
).merge()
|
||||
|
||||
val spigotToSrgSet = MappingSetMerger.create(notchToSpigotSet.reverse(), notchToSrgSet).merge()
|
||||
extraSpigotSrgMappings.fileOrNull?.toPath()?.let { path ->
|
||||
MappingFormats.TSRG.createReader(path).use { it.read(spigotToSrgSet) }
|
||||
TinyMappingFormat.STANDARD.write(spigotToNamedSet, outputMappings.path, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
}
|
||||
|
||||
private fun adjustParamIndexes(mappings: MappingSet): MappingSet {
|
||||
val indexes = hashMapOf<String, HashMap<String, HashMap<Int, Int>>>()
|
||||
|
||||
paramIndexes.file.useLines { lines ->
|
||||
lines.forEach { line ->
|
||||
val parts = line.split(" ")
|
||||
val (className, methodName, descriptor) = parts
|
||||
|
||||
val paramMap = indexes.computeIfAbsent(className) { hashMapOf() }
|
||||
.computeIfAbsent(methodName + descriptor) { hashMapOf() }
|
||||
|
||||
for (i in 3 until parts.size step 2) {
|
||||
paramMap[parts[i].toInt()] = parts[i + 1].toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val mcpToNotchSet = MappingSetMerger.create(notchToSrgSet, srgToMcpSet).merge().reverse()
|
||||
val mcpToSpigotSet = MappingSetMerger.create(mcpToNotchSet, notchToSpigotSet).merge()
|
||||
val result = MappingSet.create()
|
||||
for (old in mappings.topLevelClassMappings) {
|
||||
val new = result.createTopLevelClassMapping(old.obfuscatedName, old.deobfuscatedName)
|
||||
copyClassParam(old, new, indexes)
|
||||
}
|
||||
|
||||
val srgToSpigotSet = spigotToSrgSet.reverse()
|
||||
val spigotToMcpSet = mcpToSpigotSet.reverse()
|
||||
val spigotToNotchSet = notchToSpigotSet.reverse()
|
||||
|
||||
writeMappings(
|
||||
MappingFormats.TSRG,
|
||||
spigotToSrgSet to spigotToSrg.file,
|
||||
spigotToMcpSet to spigotToMcp.file,
|
||||
spigotToNotchSet to spigotToNotch.file,
|
||||
srgToSpigotSet to srgToSpigot.file,
|
||||
mcpToSpigotSet to mcpToSpigot.file,
|
||||
notchToSpigotSet to notchToSpigot.file
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun copyClassParam(
|
||||
from: ClassMapping<*, *>,
|
||||
to: ClassMapping<*, *>,
|
||||
params: Map<String, Map<String, Map<Int, Int>>>
|
||||
) {
|
||||
for (mapping in from.fieldMappings) {
|
||||
to.createFieldMapping(mapping.signature, mapping.deobfuscatedName)
|
||||
}
|
||||
for (mapping in from.innerClassMappings) {
|
||||
val newMapping = to.createInnerClassMapping(mapping.obfuscatedName, mapping.deobfuscatedName)
|
||||
copyClassParam(mapping, newMapping, params)
|
||||
}
|
||||
|
||||
val classMap = params[from.fullObfuscatedName]
|
||||
for (mapping in from.methodMappings) {
|
||||
val newMapping = to.createMethodMapping(mapping.signature, mapping.deobfuscatedName)
|
||||
|
||||
val paramMappings = mapping.parameterMappings
|
||||
if (paramMappings.isEmpty() || classMap == null) {
|
||||
continue
|
||||
}
|
||||
|
||||
val methodMap = classMap[mapping.signature.toJvmsIdentifier()] ?: continue
|
||||
for (paramMapping in paramMappings) {
|
||||
val i = methodMap[paramMapping.index] ?: paramMapping.index
|
||||
newMapping.createParameterMapping(i, paramMapping.deobfuscatedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private fun addSyntheticMethodMappings(mappings: MappingSet): MappingSet {
|
||||
val synths = hashMapOf<String, MutableMap<String, MutableMap<String, String>>>()
|
||||
syntheticMethods.file.useLines { lines ->
|
||||
for (line in lines) {
|
||||
val (className, desc, synthName, baseName) = line.split(" ")
|
||||
synths.computeIfAbsent(className) { hashMapOf() }
|
||||
.computeIfAbsent(desc) { hashMapOf() }[baseName] = synthName
|
||||
}
|
||||
}
|
||||
|
||||
val result = MappingSet.create()
|
||||
for (old in mappings.topLevelClassMappings) {
|
||||
val new = result.createTopLevelClassMapping(old.obfuscatedName, old.deobfuscatedName)
|
||||
copyClassSynth(old, new, synths)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun copyClassSynth(
|
||||
from: ClassMapping<*, *>,
|
||||
to: ClassMapping<*, *>,
|
||||
synths: Map<String, MutableMap<String, MutableMap<String, String>>>
|
||||
) {
|
||||
for (mapping in from.fieldMappings) {
|
||||
to.createFieldMapping(mapping.signature, mapping.deobfuscatedName)
|
||||
}
|
||||
for (mapping in from.innerClassMappings) {
|
||||
val newMapping = to.createInnerClassMapping(mapping.obfuscatedName, mapping.deobfuscatedName)
|
||||
copyClassSynth(mapping, newMapping, synths)
|
||||
}
|
||||
|
||||
val classMap = synths[from.fullObfuscatedName]
|
||||
for (mapping in from.methodMappings) {
|
||||
val names = classMap?.get(mapping.descriptor.toString())
|
||||
val newName = names?.get(mapping.obfuscatedName) ?: mapping.obfuscatedName
|
||||
|
||||
val newMapping = to.createMethodMapping(MethodSignature.of(newName, mapping.descriptor.toString()), mapping.deobfuscatedName)
|
||||
for (paramMapping in mapping.parameterMappings) {
|
||||
newMapping.createParameterMapping(paramMapping.index, paramMapping.deobfuscatedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMergerHandler {
|
||||
typealias Synths = Map<String, Map<String, Map<String, String>>>
|
||||
|
||||
class SpigotPackageMergerHandler(
|
||||
private val newPackage: String,
|
||||
private val synths: Synths
|
||||
) : MappingSetMergerHandler {
|
||||
|
||||
override fun mergeTopLevelClassMappings(
|
||||
left: TopLevelClassMapping,
|
||||
|
@ -158,6 +231,7 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
): MergeResult<TopLevelClassMapping?> {
|
||||
throw IllegalStateException("Unexpectedly merged class: ${left.fullObfuscatedName}")
|
||||
}
|
||||
|
||||
override fun mergeDuplicateTopLevelClassMappings(
|
||||
left: TopLevelClassMapping,
|
||||
right: TopLevelClassMapping,
|
||||
|
@ -171,13 +245,15 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
right
|
||||
)
|
||||
}
|
||||
|
||||
override fun addLeftTopLevelClassMapping(
|
||||
left: TopLevelClassMapping,
|
||||
target: MappingSet,
|
||||
context: MergeContext
|
||||
): MergeResult<TopLevelClassMapping?> {
|
||||
throw IllegalStateException("Unexpected added class from Spigot: ${left.fullDeobfuscatedName}")
|
||||
throw IllegalStateException("Unexpected added class from Spigot: ${left.fullObfuscatedName} - ${left.fullDeobfuscatedName}")
|
||||
}
|
||||
|
||||
override fun addRightTopLevelClassMapping(
|
||||
right: TopLevelClassMapping,
|
||||
target: MappingSet,
|
||||
|
@ -198,7 +274,6 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
context: MergeContext
|
||||
): MergeResult<InnerClassMapping?> {
|
||||
throw IllegalStateException("Unexpectedly merged class: ${left.fullObfuscatedName}")
|
||||
// return MergeResult(target.createInnerClassMapping(left.obfuscatedName, left.deobfuscatedName), right)
|
||||
}
|
||||
override fun mergeDuplicateInnerClassMappings(
|
||||
left: InnerClassMapping,
|
||||
|
@ -212,12 +287,13 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
right
|
||||
)
|
||||
}
|
||||
|
||||
override fun addLeftInnerClassMapping(
|
||||
left: InnerClassMapping,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<InnerClassMapping> {
|
||||
throw IllegalStateException("Unexpected added class from Spigot: ${left.fullDeobfuscatedName}")
|
||||
throw IllegalStateException("Unexpected added class from Spigot: ${left.fullObfuscatedName} - ${left.fullDeobfuscatedName}")
|
||||
}
|
||||
override fun addRightInnerClassMapping(
|
||||
right: InnerClassMapping,
|
||||
|
@ -246,7 +322,8 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): FieldMapping {
|
||||
return target.createFieldMapping(left.obfuscatedName, left.deobfuscatedName)
|
||||
val right = strictRightDuplicate ?: looseRightDuplicate ?: strictRightContinuation ?: looseRightContinuation ?: left
|
||||
return target.createFieldMapping(right.signature, left.deobfuscatedName)
|
||||
}
|
||||
|
||||
override fun mergeMethodMappings(
|
||||
|
@ -268,10 +345,23 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<MethodMapping?> {
|
||||
return MergeResult(target.createMethodMapping(left.signature, left.deobfuscatedName))
|
||||
// Check if Spigot calls this mapping something else
|
||||
val synthMethods = synths[left.parent.fullObfuscatedName]?.get(left.obfuscatedDescriptor)
|
||||
val newName = synthMethods?.get(left.obfuscatedName)
|
||||
return if (newName != null) {
|
||||
val newLeftMapping: MethodMapping? = (left.parent.getMethodMapping(MethodSignature.of(newName, left.obfuscatedDescriptor)) as Optional<MethodMapping>).orNull
|
||||
val newMapping = if (newLeftMapping != null) {
|
||||
target.createMethodMapping(newLeftMapping.signature, left.deobfuscatedName)
|
||||
} else {
|
||||
target.createMethodMapping(left.signature, newName)
|
||||
}
|
||||
MergeResult(newMapping)
|
||||
} else {
|
||||
MergeResult(target.createMethodMapping(left.signature, left.deobfuscatedName))
|
||||
}
|
||||
}
|
||||
|
||||
// Disable srg member mappings
|
||||
// Disable non-spigot mappings
|
||||
override fun addRightFieldMapping(
|
||||
right: FieldMapping,
|
||||
target: ClassMapping<*, *>,
|
||||
|
@ -279,12 +369,16 @@ class SpigotPackageMergerHandler(private val newPackage: String) : MappingSetMer
|
|||
): FieldMapping? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun addRightMethodMapping(
|
||||
right: MethodMapping,
|
||||
target: ClassMapping<*, *>,
|
||||
context: MergeContext
|
||||
): MergeResult<MethodMapping?> {
|
||||
return MergeResult(null)
|
||||
// Check if spigot changes this method automatically
|
||||
val synthMethods = synths[right.parent.fullObfuscatedName]?.get(right.obfuscatedDescriptor)
|
||||
val newName = synthMethods?.get(right.obfuscatedName) ?: return MergeResult(null)
|
||||
return MergeResult(target.createMethodMapping(MethodSignature.of(right.obfuscatedName, right.obfuscatedDescriptor), newName))
|
||||
}
|
||||
|
||||
private fun prependPackage(name: String): String {
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
* paperweight is a Gradle plugin for the PaperMC project. It uses
|
||||
* some code and systems originally from ForgeGradle.
|
||||
*
|
||||
* Copyright (C) 2020 Kyle Wood
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.ensureParentExists
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.fileOrNull
|
||||
import io.papermc.paperweight.util.getCsvReader
|
||||
import io.papermc.paperweight.util.path
|
||||
import io.papermc.paperweight.util.writeMappings
|
||||
import java.nio.file.Files
|
||||
import org.cadixdev.atlas.Atlas
|
||||
import org.cadixdev.bombe.asm.jar.JarEntryRemappingTransformer
|
||||
import org.cadixdev.bombe.type.signature.MethodSignature
|
||||
import org.cadixdev.lorenz.MappingSet
|
||||
import org.cadixdev.lorenz.asm.LorenzRemapper
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
import org.cadixdev.lorenz.merge.MappingSetMerger
|
||||
import org.cadixdev.lorenz.model.ClassMapping
|
||||
import org.cadixdev.lorenz.model.InnerClassMapping
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class GenerateSrgs : DefaultTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val methodsCsv: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val fieldsCsv: RegularFileProperty
|
||||
@get:Optional
|
||||
@get:InputFile
|
||||
abstract val extraNotchSrgMappings: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val inSrg: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val vanillaJar: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val notchToSrg: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val notchToMcp: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val mcpToNotch: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val mcpToSrg: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val srgToNotch: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val srgToMcp: RegularFileProperty
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val methods = HashMap<String, String>()
|
||||
val fields = HashMap<String, String>()
|
||||
readCsvs(methods, fields)
|
||||
|
||||
val inSet = MappingFormats.TSRG.createReader(inSrg.file.toPath()).use { it.read() }
|
||||
extraNotchSrgMappings.fileOrNull?.toPath()?.let { path ->
|
||||
MappingFormats.TSRG.createReader(path).use { it.read(inSet) }
|
||||
}
|
||||
|
||||
// Fill out any missing inheritance info in the mappings
|
||||
val atlasOut = Files.createTempFile("paperweight", "jar")
|
||||
try {
|
||||
Atlas().use { atlas ->
|
||||
atlas.install { ctx -> JarEntryRemappingTransformer(LorenzRemapper(inSet, ctx.inheritanceProvider())) }
|
||||
atlas.run(vanillaJar.path, atlasOut)
|
||||
}
|
||||
} finally {
|
||||
Files.deleteIfExists(atlasOut)
|
||||
}
|
||||
|
||||
ensureParentExists(notchToSrg, notchToMcp, mcpToNotch, mcpToSrg, srgToNotch, srgToMcp)
|
||||
createMappings(inSet, methods, fields)
|
||||
}
|
||||
|
||||
private fun readCsvs(methods: MutableMap<String, String>, fields: MutableMap<String, String>) {
|
||||
getCsvReader(methodsCsv.asFile.get()).use { reader ->
|
||||
for (line in reader.readAll()) {
|
||||
methods[line[0]] = line[1]
|
||||
}
|
||||
}
|
||||
|
||||
getCsvReader(fieldsCsv.asFile.get()).use { reader ->
|
||||
for (line in reader.readAll()) {
|
||||
fields[line[0]] = line[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMappings(inSet: MappingSet, methods: Map<String, String>, fields: Map<String, String>) {
|
||||
val notchToSrgSet = MappingSet.create()
|
||||
|
||||
for (mapping in inSet.topLevelClassMappings) {
|
||||
val newMapping = notchToSrgSet.createTopLevelClassMapping(mapping.obfuscatedName, mapping.deobfuscatedName)
|
||||
remapMembers(mapping, newMapping)
|
||||
}
|
||||
handleKeywordMappings(notchToSrgSet)
|
||||
|
||||
// We have Notch -> SRG
|
||||
val srgToNotchSet = notchToSrgSet.reverse()
|
||||
|
||||
val notchToMcpSet: MappingSet
|
||||
val mcpToNotchSet: MappingSet
|
||||
val mcpToSrgSet: MappingSet
|
||||
|
||||
val srgToMcpSet = MappingSet.create()
|
||||
|
||||
// Create SRG -> MCP from Notch -> SRG and the CSVs
|
||||
for (topLevelClassMapping in inSet.topLevelClassMappings) {
|
||||
// MCP and SRG have the same class names
|
||||
val srgToMcpClass = srgToMcpSet.createTopLevelClassMapping(
|
||||
topLevelClassMapping.deobfuscatedName,
|
||||
topLevelClassMapping.deobfuscatedName
|
||||
)
|
||||
|
||||
mapClass(topLevelClassMapping, srgToMcpClass, methods, fields)
|
||||
}
|
||||
|
||||
// We have Notch->SRG and SRG->MCP mapping sets now
|
||||
// All other sets can be generated from these two
|
||||
notchToMcpSet = MappingSetMerger.create(notchToSrgSet, srgToMcpSet).merge()
|
||||
mcpToNotchSet = notchToMcpSet.reverse()
|
||||
mcpToSrgSet = srgToMcpSet.reverse()
|
||||
|
||||
writeMappings(
|
||||
MappingFormats.TSRG,
|
||||
notchToSrgSet to notchToSrg.asFile.get(),
|
||||
notchToMcpSet to notchToMcp.asFile.get(),
|
||||
mcpToNotchSet to mcpToNotch.asFile.get(),
|
||||
mcpToSrgSet to mcpToSrg.asFile.get(),
|
||||
srgToNotchSet to srgToNotch.asFile.get(),
|
||||
srgToMcpSet to srgToMcp.asFile.get()
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleKeywordMappings(mappings: MappingSet) {
|
||||
for (classMapping in mappings.topLevelClassMappings) {
|
||||
handleKeywordMappingClass(classMapping)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleKeywordMappingClass(classMapping: ClassMapping<*, *>) {
|
||||
for (innerClassMapping in classMapping.innerClassMappings) {
|
||||
handleKeywordMappingClass(innerClassMapping)
|
||||
}
|
||||
for (fieldMapping in classMapping.fieldMappings) {
|
||||
if (fieldMapping.obfuscatedName in javaKeywords) {
|
||||
val sourceName = fieldMapping.obfuscatedName + '_'
|
||||
if (classMapping.hasFieldMapping(sourceName)) {
|
||||
// If the "source name" of the mapping already exists, just skip it. I don't even know what would
|
||||
// happen in this case at decompile time to be honest
|
||||
continue
|
||||
}
|
||||
classMapping.createFieldMapping(sourceName, fieldMapping.deobfuscatedName)
|
||||
}
|
||||
}
|
||||
for (methodMapping in classMapping.methodMappings) {
|
||||
if (methodMapping.obfuscatedName in javaKeywords) {
|
||||
val sourceName = methodMapping.obfuscatedName + "_"
|
||||
val sourceSignature = MethodSignature(sourceName, methodMapping.signature.descriptor)
|
||||
if (classMapping.hasMethodMapping(sourceSignature)) {
|
||||
continue
|
||||
}
|
||||
classMapping.createMethodMapping(sourceSignature, methodMapping.deobfuscatedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapClass(inClass: ClassMapping<*, *>, outClass: ClassMapping<*, *>, methods: Map<String, String>, fields: Map<String, String>) {
|
||||
for (fieldMapping in inClass.fieldMappings) {
|
||||
val mcpName = fields[fieldMapping.deobfuscatedName] ?: fieldMapping.deobfuscatedName
|
||||
val mapping = outClass.createFieldMapping(fieldMapping.deobfuscatedSignature, mcpName)
|
||||
mapping.obfuscatedName
|
||||
}
|
||||
for (methodMapping in inClass.methodMappings) {
|
||||
val mcpName = methods[methodMapping.deobfuscatedName] ?: methodMapping.deobfuscatedName
|
||||
outClass.createMethodMapping(methodMapping.deobfuscatedSignature, mcpName)
|
||||
}
|
||||
for (innerClassMapping in inClass.innerClassMappings) {
|
||||
val innerOutClass = outClass.createInnerClassMapping(innerClassMapping.deobfuscatedName)
|
||||
mapClass(innerClassMapping, innerOutClass, methods, fields)
|
||||
}
|
||||
}
|
||||
|
||||
private fun remapAnonymousClasses(mapping: InnerClassMapping, target: ClassMapping<*, *>) {
|
||||
val newMapping = target.createInnerClassMapping(mapping.obfuscatedName, mapping.deobfuscatedName)
|
||||
remapMembers(mapping, newMapping)
|
||||
}
|
||||
|
||||
private fun <T : ClassMapping<*, *>> remapMembers(mapping: T, newMapping: T) {
|
||||
for (fieldMapping in mapping.fieldMappings) {
|
||||
newMapping.createFieldMapping(fieldMapping.obfuscatedName, fieldMapping.deobfuscatedName)
|
||||
}
|
||||
for (methodMapping in mapping.methodMappings) {
|
||||
newMapping.createMethodMapping(methodMapping.signature, methodMapping.deobfuscatedName)
|
||||
}
|
||||
for (innerClassMapping in mapping.innerClassMappings) {
|
||||
remapAnonymousClasses(innerClassMapping, newMapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val javaKeywords: HashSet<String> = hashSetOf(
|
||||
"abstract",
|
||||
"continue",
|
||||
"for",
|
||||
"new",
|
||||
"switch",
|
||||
"assert",
|
||||
"default",
|
||||
"goto",
|
||||
"package",
|
||||
"synchronized",
|
||||
"boolean",
|
||||
"do",
|
||||
"if",
|
||||
"private",
|
||||
"this",
|
||||
"break",
|
||||
"double",
|
||||
"implements",
|
||||
"protected",
|
||||
"throw",
|
||||
"byte",
|
||||
"else",
|
||||
"import",
|
||||
"public",
|
||||
"throws",
|
||||
"case",
|
||||
"enum",
|
||||
"instanceof",
|
||||
"return",
|
||||
"transient",
|
||||
"catch",
|
||||
"extends",
|
||||
"int",
|
||||
"short",
|
||||
"try",
|
||||
"char",
|
||||
"final",
|
||||
"interface",
|
||||
"static",
|
||||
"void",
|
||||
"class",
|
||||
"finally",
|
||||
"long",
|
||||
"strictfp",
|
||||
"volatile",
|
||||
"const",
|
||||
"float",
|
||||
"native",
|
||||
"super",
|
||||
"while"
|
||||
)
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.AsmUtil
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
|
@ -31,7 +32,15 @@ import org.gradle.api.tasks.TaskAction
|
|||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.FieldVisitor
|
||||
import org.objectweb.asm.MethodVisitor
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.Type
|
||||
import org.objectweb.asm.tree.LabelNode
|
||||
import org.objectweb.asm.tree.LineNumberNode
|
||||
import org.objectweb.asm.tree.MethodInsnNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
import org.objectweb.asm.tree.TypeInsnNode
|
||||
import org.objectweb.asm.tree.VarInsnNode
|
||||
|
||||
abstract class InspectVanillaJar : BaseTask() {
|
||||
|
||||
|
@ -39,18 +48,32 @@ abstract class InspectVanillaJar : BaseTask() {
|
|||
abstract val inputJar: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputFile: RegularFileProperty
|
||||
abstract val loggerFile: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val paramIndexes: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val syntheticMethods: RegularFileProperty
|
||||
|
||||
override fun init() {
|
||||
outputFile.convention(defaultOutput("txt"))
|
||||
loggerFile.convention(defaultOutput("$name-loggerFields", "txt"))
|
||||
paramIndexes.convention(defaultOutput("$name-paramIndexes", "txt"))
|
||||
syntheticMethods.convention(defaultOutput("$name-syntheticMethods", "txt"))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val outputList = mutableListOf<LoggerField>()
|
||||
val loggers = mutableListOf<LoggerFields.Data>()
|
||||
val params = mutableListOf<ParamIndexes.Data>()
|
||||
val synthMethods = mutableListOf<SyntheticMethods.Data>()
|
||||
|
||||
val jarFile = inputJar.file
|
||||
archives.zipTree(jarFile).matching {
|
||||
var visitor: ClassVisitor
|
||||
visitor = LoggerFields.Visitor(null, loggers)
|
||||
visitor = ParamIndexes.Visitor(visitor, params)
|
||||
visitor = SyntheticMethods.Visitor(visitor, synthMethods)
|
||||
|
||||
archives.zipTree(inputJar.file).matching {
|
||||
include("/*.class")
|
||||
include("/net/minecraft/**/*.class")
|
||||
}.forEach { file ->
|
||||
|
@ -59,25 +82,52 @@ abstract class InspectVanillaJar : BaseTask() {
|
|||
}
|
||||
val classData = file.readBytes()
|
||||
|
||||
val reader = ClassReader(classData)
|
||||
reader.accept(LoggerFinder(outputList), 0)
|
||||
|
||||
ClassReader(classData).accept(visitor, 0)
|
||||
}
|
||||
|
||||
outputFile.file.bufferedWriter(Charsets.UTF_8).use { writer ->
|
||||
for (loggerField in outputList) {
|
||||
loggerFile.file.bufferedWriter(Charsets.UTF_8).use { writer ->
|
||||
for (loggerField in loggers) {
|
||||
writer.append(loggerField.className)
|
||||
writer.append(' ')
|
||||
writer.append(loggerField.fieldName)
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
|
||||
paramIndexes.file.bufferedWriter(Charsets.UTF_8).use { writer ->
|
||||
for (methodData in params) {
|
||||
writer.append(methodData.className)
|
||||
writer.append(' ')
|
||||
writer.append(methodData.methodName)
|
||||
writer.append(' ')
|
||||
writer.append(methodData.methodDescriptor)
|
||||
for (target in methodData.params) {
|
||||
writer.append(' ')
|
||||
writer.append(target.binaryIndex.toString())
|
||||
writer.append(' ')
|
||||
writer.append(target.sourceIndex.toString())
|
||||
}
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
|
||||
syntheticMethods.file.bufferedWriter(Charsets.UTF_8).use { writer ->
|
||||
for ((className, desc, synthName, baseName) in synthMethods) {
|
||||
writer.append(className)
|
||||
writer.append(' ')
|
||||
writer.append(desc)
|
||||
writer.append(' ')
|
||||
writer.append(synthName)
|
||||
writer.append(' ')
|
||||
writer.append(baseName)
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LoggerFinder(private val fields: MutableList<LoggerField>) : ClassVisitor(Opcodes.ASM8) {
|
||||
|
||||
private var currentClass: String? = null
|
||||
abstract class BaseClassVisitor(classVisitor: ClassVisitor?) : ClassVisitor(Opcodes.ASM8, classVisitor), AsmUtil {
|
||||
protected var currentClass: String? = null
|
||||
|
||||
override fun visit(
|
||||
version: Int,
|
||||
|
@ -88,22 +138,190 @@ class LoggerFinder(private val fields: MutableList<LoggerField>) : ClassVisitor(
|
|||
interfaces: Array<out String>?
|
||||
) {
|
||||
this.currentClass = name
|
||||
super.visit(version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SpecialSource2 automatically maps all Logger fields to the name LOGGER, without needing mappings defined, so we need
|
||||
* to make a note of all of those fields
|
||||
*/
|
||||
class LoggerFields {
|
||||
class Visitor(
|
||||
classVisitor: ClassVisitor?,
|
||||
private val fields: MutableList<Data>
|
||||
) : BaseClassVisitor(classVisitor) {
|
||||
|
||||
override fun visitField(
|
||||
access: Int,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
signature: String?,
|
||||
value: Any?
|
||||
): FieldVisitor? {
|
||||
val ret = super.visitField(access, name, descriptor, signature, value)
|
||||
val className = currentClass ?: return ret
|
||||
|
||||
if (Opcodes.ACC_STATIC !in access || Opcodes.ACC_FINAL !in access) {
|
||||
return ret
|
||||
}
|
||||
if (descriptor != "Lorg/apache/logging/log4j/Logger;") {
|
||||
return ret
|
||||
}
|
||||
fields += Data(className, name)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitField(
|
||||
data class Data(val className: String, val fieldName: String)
|
||||
}
|
||||
|
||||
/*
|
||||
* Source-remapping uses 0-based param indexes, but the param indexes we have are LVT-based. We have to look at the
|
||||
* actual bytecode to translate the LVT-based indexes back to 0-based param indexes.
|
||||
*/
|
||||
class ParamIndexes {
|
||||
class Visitor(
|
||||
classVisitor: ClassVisitor?,
|
||||
private val methods: MutableList<Data>
|
||||
) : BaseClassVisitor(classVisitor) {
|
||||
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? {
|
||||
val ret = super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||
val className = currentClass ?: return ret
|
||||
|
||||
val isStatic = access and Opcodes.ACC_STATIC != 0
|
||||
var currentIndex = if (isStatic) 0 else 1
|
||||
|
||||
val types = Type.getArgumentTypes(descriptor)
|
||||
if (types.isEmpty()) {
|
||||
return ret
|
||||
}
|
||||
|
||||
val params = ArrayList<ParamTarget>(types.size)
|
||||
val data = Data(className, name, descriptor, params)
|
||||
methods += data
|
||||
|
||||
for (i in types.indices) {
|
||||
params += ParamTarget(currentIndex, i)
|
||||
currentIndex++
|
||||
|
||||
// Figure out if we should skip the next index
|
||||
val type = types[i]
|
||||
if (type === Type.LONG_TYPE || type === Type.DOUBLE_TYPE) {
|
||||
currentIndex++
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
data class Data(
|
||||
val className: String,
|
||||
val methodName: String,
|
||||
val methodDescriptor: String,
|
||||
val params: List<ParamTarget>
|
||||
)
|
||||
|
||||
data class ParamTarget(val binaryIndex: Int, val sourceIndex: Int)
|
||||
}
|
||||
|
||||
/*
|
||||
* SpecialSource2 automatically handles certain synthetic method renames, which leads to methods which don't match any
|
||||
* existing mapping. We need to make a note of all of the synthetic methods which match SpecialSource2's checks so we
|
||||
* can handle it in our generated mappings.
|
||||
*/
|
||||
class SyntheticMethods {
|
||||
class Visitor(
|
||||
classVisitor: ClassVisitor?,
|
||||
private val methods: MutableList<Data>
|
||||
) : BaseClassVisitor(classVisitor) {
|
||||
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? {
|
||||
val ret = super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||
val className = currentClass ?: return ret
|
||||
|
||||
if (Opcodes.ACC_SYNTHETIC !in access || Opcodes.ACC_BRIDGE in access || name.contains('$')) {
|
||||
return ret
|
||||
}
|
||||
|
||||
return SynthMethodVisitor(access, name, descriptor, signature, exceptions, className, methods)
|
||||
}
|
||||
}
|
||||
|
||||
private class SynthMethodVisitor(
|
||||
access: Int,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
signature: String?,
|
||||
value: Any?
|
||||
): FieldVisitor? {
|
||||
val className = currentClass ?: return null
|
||||
if (descriptor != "Lorg/apache/logging/log4j/Logger;") {
|
||||
return null
|
||||
}
|
||||
fields += LoggerField(className, name)
|
||||
return null
|
||||
}
|
||||
}
|
||||
exceptions: Array<out String>?,
|
||||
private val className: String,
|
||||
private val methods: MutableList<Data>
|
||||
) : MethodNode(Opcodes.ASM9, access, name, descriptor, signature, exceptions) {
|
||||
|
||||
data class LoggerField(val className: String, val fieldName: String)
|
||||
// This emulates the behavior of SpecialSource2's SyntheticFinder.addSynthetics() method
|
||||
override fun visitEnd() {
|
||||
var nextLvt = 0
|
||||
|
||||
val insns = instructions.iterator().asSequence()
|
||||
.filter { it !is LabelNode && it !is LineNumberNode && it !is TypeInsnNode }
|
||||
.dropWhile {
|
||||
if (it !is VarInsnNode || it.`var` != nextLvt) {
|
||||
return@dropWhile false
|
||||
}
|
||||
|
||||
nextLvt++
|
||||
if (it.opcode == Opcodes.LLOAD || it.opcode == Opcodes.DLOAD) {
|
||||
nextLvt++
|
||||
}
|
||||
return@dropWhile true
|
||||
}
|
||||
.take(3)
|
||||
.toList()
|
||||
|
||||
// Must only have 2 instructions left
|
||||
if (insns.size != 2) {
|
||||
return
|
||||
}
|
||||
|
||||
val insn = insns.first()
|
||||
// Must be a virtual or interface invoke instruction
|
||||
if ((insn.opcode != Opcodes.INVOKEVIRTUAL && insn.opcode != Opcodes.INVOKEINTERFACE) || insn !is MethodInsnNode) {
|
||||
return
|
||||
}
|
||||
|
||||
// The next instruction must be a return
|
||||
val next = insns[1]
|
||||
if (next.opcode !in Opcodes.IRETURN..Opcodes.RETURN) {
|
||||
return
|
||||
}
|
||||
|
||||
// Must be a method in the same class with a different signature
|
||||
if (className != insn.owner || name == insn.name || desc == insn.desc) {
|
||||
return
|
||||
}
|
||||
// The descriptors need to be the same size
|
||||
if (Type.getArgumentTypes(desc).size != Type.getArgumentTypes(insn.desc).size) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add this method as a synthetic accessor for insn.name
|
||||
methods += Data(className, insn.desc, name, insn.name)
|
||||
}
|
||||
}
|
||||
|
||||
data class Data(val className: String, val desc: String, val synthName: String, val baseName: String)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ package io.papermc.paperweight.tasks
|
|||
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.path
|
||||
import org.cadixdev.at.AccessTransformSet
|
||||
import org.cadixdev.at.io.AccessTransformFormats
|
||||
import org.gradle.api.file.RegularFile
|
||||
|
@ -55,6 +56,6 @@ abstract class MergeAccessTransforms : BaseTask() {
|
|||
outputAt.merge(at)
|
||||
}
|
||||
|
||||
AccessTransformFormats.FML.write(outputFile.file.toPath(), outputAt)
|
||||
AccessTransformFormats.FML.write(outputFile.path, outputAt)
|
||||
}
|
||||
}
|
||||
|
|
53
src/main/kotlin/tasks/PatchMappings.kt
Normal file
53
src/main/kotlin/tasks/PatchMappings.kt
Normal file
|
@ -0,0 +1,53 @@
|
|||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.path
|
||||
import io.papermc.paperweight.util.pathOrNull
|
||||
import java.nio.file.Files
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class PatchMappings : DefaultTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val inputMappings: RegularFileProperty
|
||||
@get:InputFile
|
||||
@get:Optional
|
||||
abstract val patchMappings: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputMappings: RegularFileProperty
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val mappings = TinyMappingFormat.STANDARD.read(inputMappings.path, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
patchMappings.pathOrNull?.let { patchFile ->
|
||||
val temp = Files.createTempFile("patch", "tiny")
|
||||
try {
|
||||
val comment = Regex("\\s*#.*")
|
||||
// tiny format doesn't allow comments, so we manually remove them
|
||||
// The tiny mappings reader also doesn't have a InputStream or Reader input...
|
||||
Files.newBufferedReader(patchFile).useLines { lines ->
|
||||
Files.newBufferedWriter(temp).use { writer ->
|
||||
for (line in lines) {
|
||||
val newLine = comment.replace(line, "")
|
||||
if (newLine.isNotBlank()) {
|
||||
writer.appendln(newLine)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TinyMappingFormat.STANDARD.read(mappings, temp, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
} finally {
|
||||
Files.deleteIfExists(temp)
|
||||
}
|
||||
}
|
||||
|
||||
TinyMappingFormat.STANDARD.write(mappings, outputMappings.path, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* paperweight is a Gradle plugin for the PaperMC project. It uses
|
||||
* some code and systems originally from ForgeGradle.
|
||||
*
|
||||
* Copyright (C) 2020 Kyle Wood
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.util.regex.Pattern
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class PatchMcpCsv : DefaultTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val fieldsCsv: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val methodsCsv: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val paramsCsv: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val changesFile: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val paperFieldCsv: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val paperMethodCsv: RegularFileProperty
|
||||
@get:OutputFile
|
||||
abstract val paperParamCsv: RegularFileProperty
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val changes = changesFile.asFile.get().readLines()
|
||||
val changeMap = changes.asSequence()
|
||||
.filterNot { l -> l.trim().run { startsWith('#') || isEmpty() } }
|
||||
.map { l -> commentPattern.matcher(l).replaceAll("") }
|
||||
.map { l -> l.split(',').run { get(0) to get(1) } }
|
||||
.toMap()
|
||||
|
||||
val fields = fieldsCsv.asFile.get().readLines().toMutableList()
|
||||
val methods = methodsCsv.asFile.get().readLines().toMutableList()
|
||||
val params = paramsCsv.asFile.get().readLines().toMutableList()
|
||||
|
||||
replaceChanges(changeMap, fields, fieldPattern)
|
||||
replaceChanges(changeMap, methods, methodPattern)
|
||||
replaceChanges(changeMap, params, paramPattern)
|
||||
|
||||
paperFieldCsv.asFile.get().printWriter().use { writeFile(fields, it) }
|
||||
paperMethodCsv.asFile.get().printWriter().use { writeFile(methods, it) }
|
||||
paperParamCsv.asFile.get().printWriter().use { writeFile(params, it) }
|
||||
}
|
||||
|
||||
private fun replaceChanges(changes: Map<String, String>, lines: MutableList<String>, pattern: Pattern) {
|
||||
// Start at 1 to skip csv header row
|
||||
for (i in 1 until lines.size) {
|
||||
val matcher = pattern.matcher(lines[i])
|
||||
matcher.find()
|
||||
val srgName = matcher.group(1) ?: continue
|
||||
val changedName = changes[srgName] ?: continue
|
||||
lines[i] = matcher.replaceFirst("$1,$changedName,$3")
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeFile(lines: List<String>, writer: PrintWriter) {
|
||||
for (line in lines) {
|
||||
writer.println(line)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val fieldPattern = Pattern.compile("(field_\\d+_[a-zA-Z_]+),(\\w+),(\\d,.*)")
|
||||
private val methodPattern = Pattern.compile("(func_\\d+_[a-zA-Z_]+),(\\w+),(\\d,.*)")
|
||||
private val paramPattern = Pattern.compile("(p_i?\\d+_\\d+_),(\\w+),(\\d)")
|
||||
private val commentPattern = Pattern.compile("\\s*#.*")
|
||||
}
|
||||
}
|
|
@ -22,8 +22,11 @@
|
|||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.path
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.cadixdev.at.io.AccessTransformFormats
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
|
@ -47,10 +50,10 @@ abstract class RemapAccessTransform : BaseTask() {
|
|||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val at = AccessTransformFormats.FML.read(inputFile.file.toPath())
|
||||
val mappingSet = MappingFormats.TSRG.createReader(mappings.file.toPath()).use { it.read() }
|
||||
val at = AccessTransformFormats.FML.read(inputFile.path)
|
||||
val mappingSet = TinyMappingFormat.STANDARD.read(mappings.path, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
|
||||
val resultAt = at.remap(mappingSet)
|
||||
AccessTransformFormats.FML.write(outputFile.file.toPath(), resultAt)
|
||||
AccessTransformFormats.FML.write(outputFile.path, resultAt)
|
||||
}
|
||||
}
|
||||
|
|
79
src/main/kotlin/tasks/RemapJar.kt
Normal file
79
src/main/kotlin/tasks/RemapJar.kt
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* paperweight is a Gradle plugin for the PaperMC project. It uses
|
||||
* some code and systems originally from ForgeGradle.
|
||||
*
|
||||
* Copyright (C) 2020 Kyle Wood
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.Constants.paperTaskOutput
|
||||
import io.papermc.paperweight.util.cache
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.path
|
||||
import io.papermc.paperweight.util.runJar
|
||||
import javax.inject.Inject
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.cadixdev.atlas.Atlas
|
||||
import org.cadixdev.bombe.asm.jar.JarEntryRemappingTransformer
|
||||
import org.cadixdev.lorenz.asm.LorenzRemapper
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.Classpath
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.submit
|
||||
import org.gradle.workers.WorkAction
|
||||
import org.gradle.workers.WorkParameters
|
||||
import org.gradle.workers.WorkerExecutor
|
||||
|
||||
abstract class RemapJar : BaseTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val inputJar: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val mappingsFile: RegularFileProperty
|
||||
@get:Classpath
|
||||
abstract val remapper: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputJar: RegularFileProperty
|
||||
|
||||
override fun init() {
|
||||
outputJar.convention(defaultOutput())
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val logFile = layout.cache.resolve(paperTaskOutput("log"))
|
||||
logFile.delete()
|
||||
|
||||
val args = arrayOf(
|
||||
inputJar.file.absolutePath,
|
||||
outputJar.file.absolutePath,
|
||||
mappingsFile.file.absolutePath,
|
||||
Constants.OBF_NAMESPACE, Constants.DEOBF_NAMESPACE,
|
||||
"--fixpackageaccess", "--renameinvalidlocals", "--rebuildsourcefilenames"
|
||||
)
|
||||
runJar(remapper, layout.cache, logFile, jvmArgs = listOf("-Xmx512m"), args = *args);
|
||||
}
|
||||
}
|
|
@ -22,9 +22,12 @@
|
|||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.path
|
||||
import java.util.jar.JarFile
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.cadixdev.at.AccessChange
|
||||
import org.cadixdev.at.AccessTransform
|
||||
import org.cadixdev.at.AccessTransformSet
|
||||
|
@ -32,7 +35,6 @@ import org.cadixdev.at.ModifierChange
|
|||
import org.cadixdev.at.io.AccessTransformFormats
|
||||
import org.cadixdev.bombe.type.MethodDescriptor
|
||||
import org.cadixdev.bombe.type.signature.MethodSignature
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
|
@ -97,10 +99,10 @@ abstract class RemapSpigotAt : BaseTask() {
|
|||
}
|
||||
}
|
||||
|
||||
val mappings = MappingFormats.TSRG.createReader(mapping.file.toPath()).use { it.read() }
|
||||
val mappings = TinyMappingFormat.STANDARD.read(mapping.path, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
val remappedAt = outputAt.remap(mappings)
|
||||
|
||||
AccessTransformFormats.FML.write(outputFile.file.toPath(), remappedAt)
|
||||
AccessTransformFormats.FML.write(outputFile.path, remappedAt)
|
||||
}
|
||||
|
||||
private fun parseAccess(text: String): AccessTransform {
|
||||
|
|
|
@ -27,6 +27,7 @@ import io.papermc.paperweight.util.Constants.paperTaskOutput
|
|||
import io.papermc.paperweight.util.cache
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.runJar
|
||||
import java.nio.file.Paths
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
|
@ -91,8 +92,10 @@ abstract class RemapVanillaJarSpigot : BaseTask() {
|
|||
logFile.delete()
|
||||
runJar(
|
||||
specialSource2Jar,
|
||||
// Paths.get("/home/demonwav/IdeaProjects/SpecialSource2/build/libs/SpecialSource2-2.0.0-PW-SNAPSHOT-all.jar"),
|
||||
workingDir = work,
|
||||
logFile = logFile,
|
||||
// jvmArgs = listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"),
|
||||
args = *doReplacements(classMapCommand.get(), inputJarPath, classMappingPath, classJarPath) {
|
||||
// ignore excludes, we actually want to map every class
|
||||
it != "-e"
|
||||
|
@ -106,9 +109,11 @@ abstract class RemapVanillaJarSpigot : BaseTask() {
|
|||
val logFile = layout.cache.resolve(paperTaskOutput("member.log"))
|
||||
logFile.delete()
|
||||
runJar(
|
||||
// Paths.get("/home/demonwav/IdeaProjects/SpecialSource2/build/libs/SpecialSource2-2.0.0-PW-SNAPSHOT-all.jar"),
|
||||
specialSource2Jar,
|
||||
workingDir = work,
|
||||
logFile = logFile,
|
||||
// jvmArgs = listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"),
|
||||
args = *doReplacements(memberMapCommand.get(), classJarPath, memberMappingsPath, membersJarPath)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
|
|
|
@ -66,14 +66,23 @@ abstract class RunForgeFlower : BaseTask() {
|
|||
|
||||
val config = gson.fromJson<McpConfig>(configFile)
|
||||
|
||||
val argList = config.functions.decompile.args.map {
|
||||
when (it) {
|
||||
"{libraries}" -> libraries.file.absolutePath
|
||||
"{input}" -> inputJar.file.absolutePath
|
||||
"{output}" -> target.absolutePath
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
val argList = listOf(
|
||||
"-ind= ",
|
||||
"-din=1",
|
||||
"-rbr=1",
|
||||
"-dgs=1",
|
||||
"-asc=1",
|
||||
"-rsy=1",
|
||||
"-iec=1",
|
||||
"-jvn=0",
|
||||
"-isl=0",
|
||||
"-iib=1",
|
||||
"-log=TRACE",
|
||||
"-cfg",
|
||||
libraries.file.absolutePath,
|
||||
inputJar.file.absolutePath,
|
||||
target.absolutePath
|
||||
)
|
||||
|
||||
val logFile = layout.cache.resolve(paperTaskOutput("log"))
|
||||
logFile.delete()
|
||||
|
|
|
@ -22,65 +22,120 @@
|
|||
|
||||
package io.papermc.paperweight.tasks
|
||||
|
||||
import io.papermc.paperweight.util.McpConfig
|
||||
import io.papermc.paperweight.util.cache
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.fromJson
|
||||
import io.papermc.paperweight.util.gson
|
||||
import io.papermc.paperweight.util.mcinject
|
||||
import io.papermc.paperweight.util.runJar
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.util.jar.JarOutputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.file.FileVisitDetails
|
||||
import org.gradle.api.file.FileVisitor
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.logging.LoggingManager
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
|
||||
abstract class RunMcInjector : BaseTask() {
|
||||
|
||||
@get:InputFile
|
||||
abstract val configFile: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val executable: RegularFileProperty
|
||||
// @get:InputFile
|
||||
// abstract val configFile: RegularFileProperty
|
||||
// @get:InputFile
|
||||
// abstract val executable: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val exceptions: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val access: RegularFileProperty
|
||||
@get:InputFile
|
||||
abstract val constructors: RegularFileProperty
|
||||
// @get:InputFile
|
||||
// abstract val exceptions: RegularFileProperty
|
||||
// @get:InputFile
|
||||
// abstract val access: RegularFileProperty
|
||||
// @get:InputFile
|
||||
// abstract val constructors: RegularFileProperty
|
||||
|
||||
@get:InputFile
|
||||
abstract val inputJar: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputJar: RegularFileProperty
|
||||
@get:Internal
|
||||
abstract val logFile: RegularFileProperty
|
||||
// @get:Internal
|
||||
// abstract val logFile: RegularFileProperty
|
||||
|
||||
@get:Inject
|
||||
abstract val loggingManger: LoggingManager
|
||||
|
||||
override fun init() {
|
||||
outputJar.convention(defaultOutput())
|
||||
logFile.convention(defaultOutput("log"))
|
||||
// logFile.convention(defaultOutput("log"))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val config = gson.fromJson<McpConfig>(configFile)
|
||||
loggingManger.captureStandardOutput(LogLevel.QUIET)
|
||||
loggingManger.captureStandardError(LogLevel.QUIET)
|
||||
|
||||
val argList = config.functions.mcinject.args.map {
|
||||
when (it) {
|
||||
"{input}" -> inputJar.file.absolutePath
|
||||
"{output}" -> outputJar.file.absolutePath
|
||||
"{log}" -> logFile.file.absolutePath
|
||||
"{exceptions}" -> exceptions.file.absolutePath
|
||||
"{access}" -> access.file.absolutePath
|
||||
"{constructors}" -> constructors.file.absolutePath
|
||||
else -> it
|
||||
}
|
||||
val classNode = ClassNode(Opcodes.ASM6)
|
||||
var visitor: ClassVisitor
|
||||
visitor = ParameterAnnotationFixer(classNode, null)
|
||||
// visitor = InnerClassInitAdder(visitor)
|
||||
// visitor = ClassInitAdder(visitor)
|
||||
|
||||
JarOutputStream(outputJar.file.outputStream()).use { out ->
|
||||
archives.zipTree(inputJar.file).matching {
|
||||
include("/*.class")
|
||||
include("/net/minecraft/**/*.class")
|
||||
}.visit(object : FileVisitor {
|
||||
override fun visitDir(dirDetails: FileVisitDetails) {}
|
||||
override fun visitFile(fileDetails: FileVisitDetails) {
|
||||
val classData = fileDetails.file.readBytes()
|
||||
|
||||
out.putNextEntry(ZipEntry(fileDetails.path))
|
||||
try {
|
||||
val reader = ClassReader(classData)
|
||||
reader.accept(visitor, 0)
|
||||
|
||||
val writer = ClassWriter(ClassWriter.COMPUTE_MAXS)
|
||||
classNode.accept(writer)
|
||||
|
||||
ByteArrayInputStream(writer.toByteArray()).copyTo(out)
|
||||
} finally {
|
||||
out.closeEntry()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val jvmArgs = config.functions.mcinject.jvmargs ?: listOf()
|
||||
|
||||
runJar(executable, layout.cache, logFile = null, jvmArgs = jvmArgs, args = *argList.toTypedArray())
|
||||
// val config = gson.fromJson<McpConfig>(configFile)
|
||||
//
|
||||
// val argList = config.functions.mcinject.args.map {
|
||||
// when (it) {
|
||||
// "{input}" -> inputJar.file.absolutePath
|
||||
// "{output}" -> outputJar.file.absolutePath
|
||||
// "{log}" -> logFile.file.absolutePath
|
||||
// "{exceptions}" -> exceptions.file.absolutePath
|
||||
// "{access}" -> access.file.absolutePath
|
||||
// "{constructors}" -> constructors.file.absolutePath
|
||||
// else -> it
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val jvmArgs = config.functions.mcinject.jvmargs ?: listOf()
|
||||
|
||||
// runJar(
|
||||
// executable,
|
||||
// layout.cache,
|
||||
// logFile = null,
|
||||
// args = *arrayOf(
|
||||
// "--in", inputJar.file.absolutePath,
|
||||
// "--out", outputJar.file.absolutePath,
|
||||
// "--log", logFile.file.absolutePath,
|
||||
// "--level=INFO",
|
||||
// "--lvt=STRIP"
|
||||
// )
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ abstract class Filter : BaseTask() {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
abstract class Merge : BaseTask() {
|
||||
@get:InputFiles
|
||||
abstract val inputJars: ListProperty<RegularFile>
|
||||
|
@ -98,3 +99,4 @@ abstract class Merge : BaseTask() {
|
|||
target.deleteRecursively()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,7 @@ import io.papermc.paperweight.util.ensureDeleted
|
|||
import io.papermc.paperweight.util.ensureParentExists
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.orNull
|
||||
import io.papermc.paperweight.util.path
|
||||
import org.cadixdev.at.AccessChange
|
||||
import org.cadixdev.at.AccessTransform
|
||||
import org.cadixdev.at.AccessTransformSet
|
||||
|
@ -68,13 +69,13 @@ abstract class ApplyAccessTransform : BaseTask() {
|
|||
ensureParentExists(outputJar.file)
|
||||
ensureDeleted(outputJar.file)
|
||||
|
||||
val at = AccessTransformFormats.FML.read(atFile.file.toPath())
|
||||
val at = AccessTransformFormats.FML.read(atFile.path)
|
||||
|
||||
Atlas().apply {
|
||||
install {
|
||||
AtJarEntryTransformer(at)
|
||||
}
|
||||
run(inputJar.file.toPath(), outputJar.file.toPath())
|
||||
run(inputJar.path, outputJar.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,10 @@ import io.papermc.paperweight.tasks.BaseTask
|
|||
import io.papermc.paperweight.tasks.sourceremap.parseConstructors
|
||||
import io.papermc.paperweight.tasks.sourceremap.parseParamNames
|
||||
import io.papermc.paperweight.util.Git
|
||||
import io.papermc.paperweight.util.McDev
|
||||
import io.papermc.paperweight.util.cache
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.path
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
|
@ -103,7 +105,7 @@ abstract class RemapPatches : BaseTask() {
|
|||
val constructorsData = parseConstructors(constructors.file)
|
||||
val paramMap = parseParamNames(parameterNames.file)
|
||||
|
||||
val mappings = MappingFormats.TSRG.createReader(mappingsFile.file.toPath()).use { it.read() }
|
||||
val mappings = MappingFormats.TSRG.createReader(mappingsFile.path).use { it.read() }
|
||||
|
||||
// This should pull in any libraries needed for type bindings
|
||||
val configFiles = project.project(":Paper-Server").configurations["runtimeClasspath"].resolve()
|
||||
|
@ -140,7 +142,7 @@ abstract class RemapPatches : BaseTask() {
|
|||
|
||||
if (skip == 0) {
|
||||
// We need to include any missing classes for the patches later on
|
||||
importMcDev(patches, tempInputDir.resolve("src/main/java"))
|
||||
McDev.importMcDev(patches, spigotDecompJar.file, libraryImports.file, mcLibrariesDir.file, tempInputDir.resolve("src/main/java"))
|
||||
patchApplier.commitInitialSource() // Initial commit of Spigot sources
|
||||
patchApplier.checkoutRemapped() // Switch to remapped branch without checking out files
|
||||
|
||||
|
@ -169,71 +171,6 @@ abstract class RemapPatches : BaseTask() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun importMcDev(patches: Array<File>, inputDir: File) {
|
||||
val importMcDev = readMcDevNames(patches).asSequence()
|
||||
.map { inputDir.resolve("net/minecraft/server/$it.java") }
|
||||
.filter { !it.exists() }
|
||||
.toSet()
|
||||
ZipFile(spigotDecompJar.file).use { zipFile ->
|
||||
for (file in importMcDev) {
|
||||
val zipEntry = zipFile.getEntry(file.relativeTo(inputDir).path) ?: continue
|
||||
zipFile.getInputStream(zipEntry).use { input ->
|
||||
file.outputStream().buffered().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import library classes
|
||||
val libraryLines = libraryImports.file.readLines()
|
||||
if (libraryLines.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val libDir = mcLibrariesDir.file
|
||||
val libFiles = (libDir.listFiles() ?: emptyArray()).filter { it.name.endsWith("-sources.jar" )}
|
||||
if (libFiles.isEmpty()) {
|
||||
throw PaperweightException("No library files found")
|
||||
}
|
||||
|
||||
for (line in libraryLines) {
|
||||
val (libraryName, filePath) = line.split(" ")
|
||||
val libFile = libFiles.firstOrNull { it.name.startsWith(libraryName) }
|
||||
?: throw PaperweightException("Failed to find library: $libraryName for class $filePath")
|
||||
|
||||
val outputFile = inputDir.resolve(filePath)
|
||||
if (outputFile.exists()) {
|
||||
continue
|
||||
}
|
||||
outputFile.parentFile.mkdirs()
|
||||
ZipFile(libFile).use { zipFile ->
|
||||
val zipEntry = zipFile.getEntry(filePath)
|
||||
zipFile.getInputStream(zipEntry).use { input ->
|
||||
outputFile.outputStream().buffered().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun readMcDevNames(patches: Array<File>): Set<String> {
|
||||
val result = hashSetOf<String>()
|
||||
|
||||
val prefix = "+++ b/src/main/java/net/minecraft/server/"
|
||||
val suffix = ".java"
|
||||
|
||||
for (patch in patches) {
|
||||
patch.useLines { lines ->
|
||||
lines.filter { it.startsWith(prefix) }
|
||||
.mapTo(result) { it.substring(prefix.length, it.length - suffix.length) }
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createWorkDir(name: String, source: File? = null, recreate: Boolean = true): File {
|
||||
return layout.cache.resolve("paperweight").resolve(name).apply {
|
||||
if (recreate) {
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
package io.papermc.paperweight.tasks.sourceremap
|
||||
|
||||
import io.papermc.paperweight.tasks.ZippedTask
|
||||
import io.papermc.paperweight.util.Constants
|
||||
import io.papermc.paperweight.util.defaultOutput
|
||||
import io.papermc.paperweight.util.file
|
||||
import io.papermc.paperweight.util.path
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import net.fabricmc.lorenztiny.TinyMappingFormat
|
||||
import org.cadixdev.at.AccessTransformSet
|
||||
import org.cadixdev.at.io.AccessTransformFormats
|
||||
import org.cadixdev.lorenz.io.MappingFormats
|
||||
|
@ -107,7 +109,7 @@ abstract class RemapSources : ZippedTask() {
|
|||
|
||||
abstract class RemapAction : WorkAction<RemapParams> {
|
||||
override fun execute() {
|
||||
val mappingSet = MappingFormats.TSRG.read(parameters.mappings.path)
|
||||
val mappingSet = TinyMappingFormat.STANDARD.read(parameters.mappings.path, Constants.SPIGOT_NAMESPACE, Constants.DEOBF_NAMESPACE)
|
||||
val processAt = AccessTransformSet.create()
|
||||
|
||||
val constructorsData = parseConstructors(parameters.constructors.file)
|
||||
|
|
7
src/main/kotlin/util/AsmUtil.kt
Normal file
7
src/main/kotlin/util/AsmUtil.kt
Normal file
|
@ -0,0 +1,7 @@
|
|||
package io.papermc.paperweight.util
|
||||
|
||||
interface AsmUtil {
|
||||
operator fun Int.contains(value: Int): Boolean {
|
||||
return value and this == value
|
||||
}
|
||||
}
|
|
@ -31,6 +31,9 @@ object Constants {
|
|||
const val MC_LIBRARY_URL = "https://libraries.minecraft.net/"
|
||||
const val MC_MANIFEST_URL = "https://launchermeta.mojang.com/mc/game/version_manifest.json"
|
||||
|
||||
const val YARN_CONFIG = "yarn"
|
||||
const val REMAPPER_CONFIG = "remapper"
|
||||
|
||||
const val CACHE_PATH = "caches"
|
||||
private const val PAPER_PATH = "paperweight"
|
||||
|
||||
|
@ -42,7 +45,12 @@ object Constants {
|
|||
|
||||
const val MCP_DATA_DIR = "mcp/data"
|
||||
const val MCP_MAPPINGS_DIR = "mcp/mappings"
|
||||
private const val SRG_DIR = "$MCP_MAPPINGS_DIR/srgs"
|
||||
const val SERVER_MAPPINGS = "mcp/server_mappings.txt"
|
||||
const val SRG_DIR = "$MCP_MAPPINGS_DIR/srgs"
|
||||
|
||||
const val OBF_NAMESPACE = "official"
|
||||
const val SPIGOT_NAMESPACE = "spigot"
|
||||
const val DEOBF_NAMESPACE = "mojang+yarn"
|
||||
|
||||
const val MCP_CONFIG_JSON = "$MCP_DATA_DIR/config.json"
|
||||
|
||||
|
|
73
src/main/kotlin/util/McDev.kt
Normal file
73
src/main/kotlin/util/McDev.kt
Normal file
|
@ -0,0 +1,73 @@
|
|||
package io.papermc.paperweight.util
|
||||
|
||||
import io.papermc.paperweight.PaperweightException
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
object McDev {
|
||||
|
||||
fun importMcDev(patches: Array<File>, decompJar: File, libraryImports: File, libraryDir: File, targetDir: File) {
|
||||
val importMcDev = readMcDevNames(patches).asSequence()
|
||||
.map { targetDir.resolve("net/minecraft/server/$it.java") }
|
||||
.filter { !it.exists() }
|
||||
.toSet()
|
||||
|
||||
ZipFile(decompJar).use { zipFile ->
|
||||
for (file in importMcDev) {
|
||||
val zipEntry = zipFile.getEntry(file.relativeTo(targetDir).path) ?: continue
|
||||
zipFile.getInputStream(zipEntry).use { input ->
|
||||
file.outputStream().buffered().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Import library classes
|
||||
val libraryLines = libraryImports.readLines()
|
||||
if (libraryLines.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val libFiles = (libraryDir.listFiles() ?: emptyArray()).filter { it.name.endsWith("-sources.jar" )}
|
||||
if (libFiles.isEmpty()) {
|
||||
throw PaperweightException("No library files found")
|
||||
}
|
||||
|
||||
for (line in libraryLines) {
|
||||
val (libraryName, filePath) = line.split(" ")
|
||||
val libFile = libFiles.firstOrNull { it.name.startsWith(libraryName) }
|
||||
?: throw PaperweightException("Failed to find library: $libraryName for class $filePath")
|
||||
|
||||
val outputFile = targetDir.resolve(filePath)
|
||||
if (outputFile.exists()) {
|
||||
continue
|
||||
}
|
||||
outputFile.parentFile.mkdirs()
|
||||
ZipFile(libFile).use { zipFile ->
|
||||
val zipEntry = zipFile.getEntry(filePath)
|
||||
zipFile.getInputStream(zipEntry).use { input ->
|
||||
outputFile.outputStream().buffered().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun readMcDevNames(patches: Array<File>): Set<String> {
|
||||
val result = hashSetOf<String>()
|
||||
|
||||
val prefix = "+++ b/src/main/java/net/minecraft/server/"
|
||||
val suffix = ".java"
|
||||
|
||||
for (patch in patches) {
|
||||
patch.useLines { lines ->
|
||||
lines.filter { it.startsWith(prefix) }
|
||||
.mapTo(result) { it.substring(prefix.length, it.length - suffix.length) }
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -25,17 +25,12 @@ package io.papermc.paperweight.util
|
|||
import io.papermc.paperweight.PaperweightException
|
||||
import java.io.OutputStream
|
||||
import org.gradle.internal.jvm.Jvm
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
fun runJar(jar: Any, workingDir: Any, logFile: Any?, jvmArgs: List<String> = listOf(), vararg args: String) {
|
||||
val jarFile = jar.convertToFile()
|
||||
val dir = workingDir.convertToFile()
|
||||
|
||||
val process = ProcessBuilder(
|
||||
Jvm.current().javaExecutable.canonicalPath, *jvmArgs.toTypedArray(),
|
||||
"-jar", jarFile.canonicalPath,
|
||||
*args
|
||||
).directory(dir).start()
|
||||
|
||||
val output = when {
|
||||
logFile is OutputStream -> logFile
|
||||
logFile != null -> {
|
||||
|
@ -45,6 +40,19 @@ fun runJar(jar: Any, workingDir: Any, logFile: Any?, jvmArgs: List<String> = lis
|
|||
else -> UselessOutputStream
|
||||
}
|
||||
|
||||
val processBuilder = ProcessBuilder(
|
||||
Jvm.current().javaExecutable.canonicalPath, *jvmArgs.toTypedArray(),
|
||||
"-jar", jarFile.canonicalPath,
|
||||
*args
|
||||
).directory(dir)
|
||||
|
||||
output.writer().let {
|
||||
it.appendln("Command: ${processBuilder.command().joinToString(" ")}")
|
||||
it.flush()
|
||||
}
|
||||
|
||||
val process = processBuilder.start()
|
||||
|
||||
output.use {
|
||||
redirect(process.inputStream, it)
|
||||
redirect(process.errorStream, it)
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
|
||||
package io.papermc.paperweight.util
|
||||
|
||||
import au.com.bytecode.opencsv.CSVParser
|
||||
import au.com.bytecode.opencsv.CSVReader
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.Gson
|
||||
import com.opencsv.CSVParserBuilder
|
||||
import com.opencsv.CSVReader
|
||||
import com.opencsv.CSVReaderBuilder
|
||||
import io.papermc.paperweight.PaperweightException
|
||||
import io.papermc.paperweight.ext.PaperweightExtension
|
||||
import io.papermc.paperweight.tasks.BaseTask
|
||||
|
@ -85,14 +86,9 @@ object UselessOutputStream : OutputStream() {
|
|||
}
|
||||
}
|
||||
|
||||
fun getCsvReader(file: File) = CSVReader(
|
||||
file.reader(),
|
||||
CSVParser.DEFAULT_SEPARATOR,
|
||||
CSVParser.DEFAULT_QUOTE_CHARACTER,
|
||||
CSVParser.NULL_CHARACTER,
|
||||
1,
|
||||
false
|
||||
)
|
||||
fun getCsvReader(file: File): CSVReader = CSVReaderBuilder(file.bufferedReader())
|
||||
.withCSVParser(CSVParserBuilder().withStrictQuotes(false).build())
|
||||
.build()
|
||||
|
||||
fun Any.convertToFile(): File {
|
||||
return when (this) {
|
||||
|
@ -153,6 +149,8 @@ val RegularFileProperty.fileOrNull: File?
|
|||
get() = orNull?.asFile
|
||||
val RegularFileProperty.path: Path
|
||||
get() = file.toPath()
|
||||
val RegularFileProperty.pathOrNull: Path?
|
||||
get() = fileOrNull?.toPath()
|
||||
val DirectoryProperty.file: File
|
||||
get() = get().asFile
|
||||
val DirectoryProperty.path: Path
|
||||
|
|
Loading…
Reference in a new issue