From c9abaea8aecda78e3dfad7d66256bbb8b4a93255 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 14 Feb 2021 21:57:26 +0800 Subject: [PATCH] Bump as 3.0, migrate to archtiectury runtime transformer --- build.gradle | 4 +- gradle.properties | 5 +- .../architect/plugin/ArchitectPlugin.kt | 51 ++-- .../plugin/ArchitectPluginExtension.kt | 203 +++++++++++++--- .../architect/plugin/TransformingTask.kt | 80 +------ .../plugin/transformers/AddRefmapName.kt | 73 +++--- .../plugin/transformers/FixForgeMixin.kt | 220 ------------------ .../transformers/GenerateFakeFabricModJson.kt | 31 --- .../transformers/GenerateFakeForgeMod.kt | 52 ----- .../transformers/RemapMixinVariables.kt | 68 +----- .../transformers/RemoveFabricModJson.kt | 19 -- .../transformers/TransformExpectPlatform.kt | 206 ---------------- .../transformers/TransformForgeBytecode.kt | 72 ------ .../transformers/TransformForgeEnvironment.kt | 104 --------- .../transformers/TransformInjectables.kt | 69 ------ .../architect/plugin/utils/FileSystemUtils.kt | 25 -- 16 files changed, 252 insertions(+), 1030 deletions(-) delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/FixForgeMixin.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeFabricModJson.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeForgeMod.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemoveFabricModJson.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformExpectPlatform.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeBytecode.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeEnvironment.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformInjectables.kt delete mode 100644 src/main/kotlin/me/shedaniel/architect/plugin/utils/FileSystemUtils.kt diff --git a/build.gradle b/build.gradle index a7587d5..a983981 100644 --- a/build.gradle +++ b/build.gradle @@ -26,10 +26,9 @@ logger.lifecycle(":building architectury plugin v${version}") sourceCompatibility = targetCompatibility = 1.8 repositories { - jcenter() maven { url "https://maven.fabricmc.net/" } maven { url "https://files.minecraftforge.net/maven/" } - maven { url "https://dl.bintray.com/shedaniel/cloth/" } + maven { url "https://maven.shedaniel.me/" } gradlePluginPortal() } @@ -44,6 +43,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72" implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.72" implementation "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:0.10" + implementation "me.shedaniel:architectury-transformer:$transformer_version" implementation "me.shedaniel:forgified-fabric-loom:$loom_version" runtime "me.shedaniel:forgified-fabric-loom:$loom_version" implementation "net.fabricmc:tiny-remapper:0.3.0.70" diff --git a/gradle.properties b/gradle.properties index 89b3936..06f2427 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ kotlin.code.style=official -loom_version=0.6.54 -base_version=2.0 \ No newline at end of file +loom_version=0.6.67 +transformer_version=2.0.7 +base_version=3.0 \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPlugin.kt b/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPlugin.kt index ade28c8..ab40811 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPlugin.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPlugin.kt @@ -1,6 +1,8 @@ package me.shedaniel.architect.plugin -import me.shedaniel.architect.plugin.transformers.* +import me.shedaniel.architect.plugin.transformers.AddRefmapName +import me.shedaniel.architect.plugin.transformers.RemapMixinVariables +import me.shedaniel.architectury.transformer.transformers.* import net.fabricmc.loom.util.LoggerFilter import org.gradle.api.Plugin import org.gradle.api.Project @@ -43,49 +45,32 @@ class ArchitectPlugin : Plugin { project.extensions.create("architectury", ArchitectPluginExtension::class.java, project) + project.configurations.create("transformFabric") + project.configurations.create("transformForge") + project.tasks.register("transformProductionFabric", TransformingTask::class.java) { it.group = "Architectury" - it(RemapMixinVariables) - it(TransformExpectPlatform) - it(TransformInjectables) - it(AddRefmapName) - } - - project.tasks.register("transformDevelopmentFabric", TransformingTask::class.java) { - it.group = "Architectury" - it(GenerateFakeFabricModJson) - it(TransformExpectPlatform) - it(TransformInjectables) + it += RemapMixinVariables(project) + it += TransformExpectPlatform() + it += RemapInjectables() + it += AddRefmapName(project) } project.tasks.register("transformProductionForge", TransformingTask::class.java) { it.group = "Architectury" - it(RemapMixinVariables) - it(TransformExpectPlatform) - it(TransformInjectables) - it(AddRefmapName) + it += RemapMixinVariables(project) + it += TransformExpectPlatform() + it += RemapInjectables() + it += AddRefmapName(project) - it(TransformForgeBytecode) - it(RemoveFabricModJson) - it(TransformForgeEnvironment) - it(FixForgeMixin) - } - - project.tasks.register("transformDevelopmentForge", TransformingTask::class.java) { - it.group = "Architectury" - it(TransformExpectPlatform) - it(TransformInjectables) - - it(TransformForgeBytecode) - it(RemoveFabricModJson) - it(TransformForgeEnvironment) - it(GenerateFakeForgeMod) - it(FixForgeMixin) + it += TransformForgeAnnotations() + it += TransformForgeEnvironment() + it += FixForgeMixin() } project.repositories.apply { mavenCentral() - maven { it.url = URI("https://dl.bintray.com/shedaniel/cloth") } + maven { it.url = URI("https://maven.shedaniel.me/") } } } } diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt b/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt index 8ec19cb..f1677ce 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt @@ -2,41 +2,177 @@ package me.shedaniel.architect.plugin +import me.shedaniel.architectury.transformer.Transformer +import me.shedaniel.architectury.transformer.transformers.* import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.task.RemapJarTask +import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.tasks.bundling.AbstractArchiveTask import java.io.File +import java.lang.IllegalStateException +import java.nio.file.Path +import java.util.* +import java.util.function.Consumer import java.util.jar.JarOutputStream import java.util.jar.Manifest open class ArchitectPluginExtension(val project: Project) { + var transformerVersion = "2.0.7" var minecraft = "" var injectInjectables = true + private val transforms = mutableMapOf() + private var transformedLoom = false + private val agentFile by lazy { + project.gradle.rootProject.file(".gradle/architectury/architectury-transformer-agent.jar").also { + it.parentFile.mkdirs() + } + } + private val mainClassTransformerFile by lazy { + project.file(".gradle/architectury/.main_class").also { + it.parentFile.mkdirs() + } + } + private val runtimeTransformerFile by lazy { + project.file(".gradle/architectury/.transforms").also { + it.parentFile.mkdirs() + } + } + private val propertiesTransformerFile by lazy { + project.file(".gradle/architectury/.properties").also { + it.parentFile.mkdirs() + } + } + + init { + project.afterEvaluate { + if (transforms.isNotEmpty()) { + val transformPaths = mutableMapOf>>() + for (transform in transforms.values) { + project.configurations.getByName(transform.configName).forEach { + transformPaths[it.toPath()] = transform.transformers + } + } + transformPaths.asSequence().flatMap { it.value.asSequence().map { c -> it.key to c } } + .joinToString(File.pathSeparator) { "${it.first}|${it.second.name}" } + .also { + runtimeTransformerFile.writeText(it) + } + } + + val properties = Properties() + properties().forEach { (key, value) -> + System.setProperty(key, value) + properties.setProperty(key, value) + } + propertiesTransformerFile.writer().use { + properties.store(it, "Architectury Runtime Transformer Properties") + } + } + } + + private fun properties(): Map { + val loom = project.extensions.findByType(LoomGradleExtension::class.java) ?: return mapOf() + return mutableMapOf( + BuiltinProperties.MIXIN_MAPPINGS to loom.allMixinMappings.joinToString(File.pathSeparator), + BuiltinProperties.INJECT_INJECTABLES to injectInjectables.toString(), + BuiltinProperties.UNIQUE_IDENTIFIER to project.projectUniqueIdentifier(), + BuiltinProperties.COMPILE_CLASSPATH to project.configurations.getByName("compileClasspath") + .joinToString(File.pathSeparator), + BuiltinProperties.MAPPINGS_WITH_SRG to loom.mappingsProvider.tinyMappingsWithSrg.toString(), + BuiltinProperties.REFMAP_NAME to loom.refmapName, + BuiltinProperties.MCMETA_VERSION to "4" + ) + } + + fun transform(name: String, action: Action) { + transforms.getOrPut(name) { + Transform("development" + name.capitalize()).also { transform -> + project.configurations.create(transform.configName) + + if (!transformedLoom) { + val architecturyJavaAgents = project.configurations.create("architecturyJavaAgents") { + project.configurations.getByName("runtimeOnly").extendsFrom(it) + } + transformedLoom = true + + with(project.dependencies) { + add("runtimeOnly", "me.shedaniel:architectury-transformer:$transformerVersion:runtime") + add("architecturyJavaAgents", "me.shedaniel:architectury-transformer:$transformerVersion:agent") + } + + val loom = project.extensions.getByType(LoomGradleExtension::class.java) + loom.settingsPostEdit.add(Consumer { config -> + val s = config.mainClass + config.mainClass = "me.shedaniel.architectury.transformer.TransformerRuntime" + mainClassTransformerFile.writeText(s) + config.vmArgs += " -Darchitectury.main.class=$mainClassTransformerFile" + config.vmArgs += " -Darchitectury.runtime.transformer=$runtimeTransformerFile" + config.vmArgs += " -Darchitectury.properties=$propertiesTransformerFile" + config.vmArgs += " -Djdk.attach.allowAttachSelf=true" + if (architecturyJavaAgents.toList().size == 1) { + architecturyJavaAgents.first().copyTo(agentFile, overwrite = true) + config.vmArgs += " -javaagent:${agentFile.absolutePath}" + } else { + throw IllegalStateException("Illegal Count of Architectury Java Agents! " + architecturyJavaAgents.toList().joinToString(", ")) + } + }) + } + } + }.also { + action.execute(it) + } + } + + fun fabric() { + transform("fabric", Action { + it.setupFabricTransforms() + }) + } + + fun forge() { + transform("forge", Action { + it.setupForgeTransforms() + }) + } fun common() { - common(true) + common {} } + data class CommonSettings( + var forgeEnabled: Boolean = true + ) + fun platformSetupLoomIde() { val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java) - loomExtension.autoGenIDERuns = true + loomExtension.runConfigs.forEach { it.isIdeConfigGenerated = true } + loomExtension.runConfigs.whenObjectAdded { it.isIdeConfigGenerated = true } loomExtension.addTaskBeforeRun("\$PROJECT_DIR\$/${project.name}:classes") } fun common(forgeEnabled: Boolean) { + common { + this.forgeEnabled = forgeEnabled + } + } + + fun common(action: CommonSettings.() -> Unit) { + common(Action { it.action() }) + } + + fun common(action: Action) { + val settings = CommonSettings().also { action.execute(it) } if (injectInjectables) { with(project.dependencies) { add("compileOnly", "me.shedaniel:architectury-injectables:1.0.4") } } - if (forgeEnabled) { + if (settings.forgeEnabled) { project.configurations.create("transformProductionForge") - project.configurations.create("transformDevelopmentForge") } project.configurations.create("transformProductionFabric") - project.configurations.create("transformDevelopmentFabric") val buildTask = project.tasks.getByName("build") val jarTask = project.tasks.getByName("jar") { @@ -55,19 +191,6 @@ open class ArchitectPluginExtension(val project: Project) { buildTask.dependsOn(it) it.outputs.upToDateWhen { false } } as TransformingTask - val transformDevelopmentFabricTask = project.tasks.getByName("transformDevelopmentFabric") { - it as TransformingTask - - it.archiveClassifier.set("transformDevelopmentFabric") - it.input.set(jarTask.archiveFile.get()) - - project.artifacts.add("transformDevelopmentFabric", it) - it.dependsOn(jarTask) - buildTask.dependsOn(it) - it.outputs.upToDateWhen { false } - } as TransformingTask - - transformProductionFabricTask.dependsOn(transformDevelopmentFabricTask) val remapJarTask = project.tasks.getByName("remapJar") { it as RemapJarTask @@ -78,7 +201,7 @@ open class ArchitectPluginExtension(val project: Project) { it.mustRunAfter(transformProductionFabricTask) } as RemapJarTask - if (forgeEnabled) { + if (settings.forgeEnabled) { val transformProductionForgeTask = project.tasks.getByName("transformProductionForge") { it as TransformingTask @@ -91,30 +214,12 @@ open class ArchitectPluginExtension(val project: Project) { it.outputs.upToDateWhen { false } } as TransformingTask - val transformDevelopmentForgeTask = project.tasks.getByName("transformDevelopmentForge") { - it as TransformingTask - - it.input.set(jarTask.archiveFile.get()) - it.archiveClassifier.set("transformDevelopmentForge") - - project.artifacts.add("transformDevelopmentForge", it) { artifact -> - artifact.builtBy(it) - } - it.dependsOn(jarTask) - buildTask.dependsOn(it) - it.outputs.upToDateWhen { false } - } as TransformingTask - - transformProductionForgeTask.dependsOn(transformDevelopmentForgeTask) - transformProductionForgeTask.archiveFile.get().asFile.takeUnless { it.exists() }?.createEmptyJar() - transformDevelopmentForgeTask.archiveFile.get().asFile.takeUnless { it.exists() }?.createEmptyJar() project.extensions.getByType(LoomGradleExtension::class.java).generateSrgTiny = true } transformProductionFabricTask.archiveFile.get().asFile.takeUnless { it.exists() }?.createEmptyJar() - transformDevelopmentFabricTask.archiveFile.get().asFile.takeUnless { it.exists() }?.createEmptyJar() } } @@ -122,3 +227,27 @@ private fun File.createEmptyJar() { parentFile.mkdirs() JarOutputStream(outputStream(), Manifest()).close() } + +data class Transform(val configName: String, val transformers: MutableList> = mutableListOf()) { + fun setupFabricTransforms() { + this += GenerateFakeFabricMod::class.java + this += TransformExpectPlatform::class.java + this += RemapInjectables::class.java + } + + fun setupForgeTransforms() { + this += TransformExpectPlatform::class.java + this += RemapInjectables::class.java + + this += TransformForgeAnnotations::class.java + this += TransformForgeEnvironment::class.java + this += GenerateFakeForgeMod::class.java + this += FixForgeMixin::class.java + } + + operator fun plusAssign(transformer: Class) { + transformers.add(transformer as Class) + } + + fun add(transformer: Class) = plusAssign(transformer as Class) +} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/TransformingTask.kt b/src/main/kotlin/me/shedaniel/architect/plugin/TransformingTask.kt index e2e7a42..649b156 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/TransformingTask.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/TransformingTask.kt @@ -1,97 +1,43 @@ package me.shedaniel.architect.plugin import me.shedaniel.architect.plugin.utils.GradleSupport +import me.shedaniel.architectury.transformer.Transform +import me.shedaniel.architectury.transformer.Transformer import org.gradle.api.Project import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.jvm.tasks.Jar import java.io.File -import java.io.ObjectOutputStream -import java.io.Serializable -import java.nio.file.Files import java.nio.file.Path -import java.nio.file.StandardCopyOption import java.util.* import kotlin.properties.Delegates -import kotlin.time.Duration import kotlin.time.ExperimentalTime -import kotlin.time.nanoseconds open class TransformingTask : Jar() { @InputFile val input: RegularFileProperty = GradleSupport.getFileProperty(project) - - @Input + @Internal val transformers = mutableListOf() @ExperimentalTime @TaskAction fun doTask() { val input: Path = this.input.asFile.get().toPath() - val taskOutputs = transformers.mapIndexed { index, _ -> - project.file("build") - .resolve("architectury-plugin/" + input.toFile().nameWithoutExtension + "-intermediate-${index}.jar") - .toPath() - } val output: Path = this.archiveFile.get().asFile.toPath() - transformers.forEachIndexed { index, transformer -> - val i = if (index == 0) input else taskOutputs[index - 1] - val o = taskOutputs[index] - - Files.deleteIfExists(o) - Files.createDirectories(o.parent) - runCatching { - var skipped = false - measureTime { - try { - transformer(project, i, o) - } catch (ignored: TransformerStepSkipped) { - skipped = true - } - if (index != 0) { - Files.deleteIfExists(i) - } - }.let { duration -> - if (skipped) { - project.logger.lifecycle(":skipped transforming step ${index + 1}/${transformers.size} [${transformer::class.simpleName}] in $duration") - } else { - project.logger.lifecycle(":finished transforming step ${index + 1}/${transformers.size} [${transformer::class.simpleName}] in $duration") - } - } - }.onFailure { - throw RuntimeException( - "Failed transformer step ${index + 1}/${transformers.size} [${transformer::class.simpleName}]", - it - ) - } - - runCatching { - o.toFile().also { it.renameTo(it) } - }.onFailure { - throw RuntimeException( - "Transformer step ${index + 1}/${transformers.size} [${transformer::class.simpleName}] did not properly close the output file!", - it - ) - } - } - - Files.move(taskOutputs.last(), output, StandardCopyOption.REPLACE_EXISTING) + Transform.runTransformers(input, output, transformers) } operator fun invoke(transformer: Transformer) { transformers.add(transformer) } -} -@ExperimentalTime -private inline fun measureTime(block: () -> Unit): Duration { - val current = System.nanoTime() - block() - val finished = System.nanoTime() - return (finished - current).nanoseconds + operator fun plusAssign(transformer: Transformer) { + transformers.add(transformer) + } } fun Project.projectUniqueIdentifier(): String { @@ -109,13 +55,3 @@ fun Project.projectUniqueIdentifier(): String { if (project.rootProject != project) name = project.rootProject.name + "_" + name return "architectury_inject_${name}_$id".filter { Character.isJavaIdentifierPart(it) } } - -interface Transformer : Serializable { - operator fun invoke(project: Project, input: Path, output: Path) - - @JvmDefault - fun writeObject(s: ObjectOutputStream) { - } -} - -object TransformerStepSkipped : Throwable() \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/AddRefmapName.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/AddRefmapName.kt index d695c10..5bc9f9d 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/AddRefmapName.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/AddRefmapName.kt @@ -1,44 +1,57 @@ package me.shedaniel.architect.plugin.transformers -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.TransformerStepSkipped +import com.google.gson.JsonObject +import me.shedaniel.architectury.transformer.Transformer +import me.shedaniel.architectury.transformer.TransformerStepSkipped +import me.shedaniel.architectury.transformer.transformers.base.AssetEditTransformer +import me.shedaniel.architectury.transformer.transformers.base.edit.AssetEditSink +import me.shedaniel.architectury.transformer.transformers.base.edit.TransformerContext import net.fabricmc.loom.LoomGradleExtension +import net.fabricmc.loom.LoomGradlePlugin import org.gradle.api.Project +import java.io.ByteArrayInputStream import java.nio.file.Files import java.nio.file.Path +import java.util.* -object AddRefmapName : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - Files.copy(input, output) +class AddRefmapName(private val project: Project) : AssetEditTransformer { + override fun doEdit(context: TransformerContext, sink: AssetEditSink) { val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java) - var refmapHelperClass: Class<*>? = null - runCatching { - refmapHelperClass = Class.forName("net.fabricmc.loom.util.MixinRefmapHelper") - }.onFailure { - runCatching { - refmapHelperClass = Class.forName("net.fabricmc.loom.build.MixinRefmapHelper") - }.onFailure { - throw ClassNotFoundException("Failed to find MixinRefmapHelper!") + + val mixins = mutableSetOf() + sink.handle { path, bytes -> + // Check JSON file in root directory + if (path.endsWith(".json") && !path.contains("/") && !path.contains("\\")) { + try { + val json = + LoomGradlePlugin.GSON.fromJson(ByteArrayInputStream(bytes).reader(), JsonObject::class.java) + if (json != null) { + val hasMixins = json.has("mixins") && json["mixins"].isJsonArray + val hasClient = json.has("client") && json["client"].isJsonArray + val hasServer = json.has("server") && json["server"].isJsonArray + if (json.has("package") && (hasMixins || hasClient || hasServer)) { + if (!json.has("refmap") || !json.has("minVersion")) { + mixins.add(path) + } + } + } + } catch (_: Exception) { + } } } + mixins.forEach { path -> + sink.transformFile(path) { + val json: JsonObject = LoomGradlePlugin.GSON.fromJson( + ByteArrayInputStream(it).reader(), + JsonObject::class.java + ) - val method = refmapHelperClass!!.getDeclaredMethod( - "addRefmapName", - String::class.java, - String::class.java, - Path::class.java - ) - if ( - method.invoke( - null, - loomExtension.getRefmapName(), - loomExtension.mixinJsonVersion, - output - ) as Boolean - ) { - project.logger.debug("Transformed mixin reference maps in output JAR!") - } else { - throw TransformerStepSkipped + if (!json.has("refmap")) { + json.addProperty("refmap", loomExtension.getRefmapName()) + } + + LoomGradlePlugin.GSON.toJson(json).toByteArray() + } } } } \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/FixForgeMixin.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/FixForgeMixin.kt deleted file mode 100644 index 9edb129..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/FixForgeMixin.kt +++ /dev/null @@ -1,220 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import com.google.gson.GsonBuilder -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.TransformerStepSkipped -import net.fabricmc.loom.LoomGradleExtension -import org.gradle.api.Project -import org.zeroturnaround.zip.ZipUtil -import java.io.File -import java.io.IOException -import java.io.InputStreamReader -import java.io.StringReader -import java.nio.file.Files -import java.nio.file.Path -import java.util.jar.Manifest -import java.util.zip.ZipEntry - -object FixForgeMixin : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - Files.copy(input, output) - fixMixins(project, output.toFile()) - } - - private fun fixMixins(project: Project, output: File) { - val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java) - val gson = GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create() - val mixinConfigs = mutableListOf() - val refmap = loomExtension.getRefmapName() - ZipUtil.iterate(output) { stream, entry -> - if (!entry.isDirectory && entry.name.endsWith(".json") && - !entry.name.contains("/") && !entry.name.contains("\\") - ) { - try { - InputStreamReader(stream).use { reader -> - val json: JsonObject? = gson.fromJson(reader, JsonObject::class.java) - if (json != null) { - val hasMixins = json.has("mixins") && json["mixins"].isJsonArray - val hasClient = json.has("client") && json["client"].isJsonArray - val hasServer = json.has("server") && json["server"].isJsonArray - if (json.has("package") && (hasMixins || hasClient || hasServer)) { - mixinConfigs.add(entry.name) - } - } - } - } catch (ignored: Exception) { - } - } - } - if (mixinConfigs.isNotEmpty()) { - if (ZipUtil.containsEntry(output, "META-INF/MANIFEST.MF")) { - ZipUtil.transformEntry(output, "META-INF/MANIFEST.MF") { input, zipEntry, out -> - val manifest = Manifest(input) - manifest.mainAttributes.putValue("MixinConfigs", mixinConfigs.joinToString(",")) - out.putNextEntry(ZipEntry(zipEntry.name)) - manifest.write(out) - out.closeEntry() - } - } - } - if (ZipUtil.containsEntry(output, refmap)) { - ZipUtil.transformEntry(output, refmap) { input, zipEntry, out -> - val refmapElement: JsonObject = JsonParser().parse(InputStreamReader(input)).asJsonObject.deepCopy() - if (refmapElement.has("mappings")) { - refmapElement["mappings"].asJsonObject.entrySet().forEach { (_, value) -> - remapRefmap(project, value.asJsonObject) - } - } - if (refmapElement.has("data")) { - val data = refmapElement["data"].asJsonObject - if (data.has("named:intermediary")) { - data.add("searge", data["named:intermediary"].deepCopy().also { - it.asJsonObject.entrySet().forEach { (_, value) -> - remapRefmap(project, value.asJsonObject) - } - }) - data.remove("named:intermediary") - } - } - out.putNextEntry(ZipEntry(zipEntry.name)) - out.write(gson.toJson(refmapElement).toByteArray()) - out.closeEntry() - } - } else { - project.logger.info("Failed to locate refmap: $refmap") - if (mixinConfigs.isEmpty()) { - throw TransformerStepSkipped - } - } - } - - private fun remapRefmap(project: Project, obj: JsonObject) { - val srg = project.extensions.getByType(LoomGradleExtension::class.java).mappingsProvider.mappingsWithSrg - val methodPattern = "L(.*);(.*)(\\(.*)".toRegex() - val methodPatternWithoutClass = "(.*)(\\(.*)".toRegex() - val fieldPattern = "L(.*);(.*):(.*)".toRegex() - val fieldPatternWithoutClass = "(.*):(.*)".toRegex() - - obj.keySet().forEach { key -> - val originalRef = obj[key].asString - - val methodMatch = methodPattern.matchEntire(originalRef) - val fieldMatch = fieldPattern.matchEntire(originalRef) - val fieldMatchWithoutClass = fieldPatternWithoutClass.matchEntire(originalRef) - val methodMatchWithoutClass = methodPatternWithoutClass.matchEntire(originalRef) - val classMatch = srg.classes.firstOrNull { it.getName("intermediary") == originalRef } - - when { - methodMatch != null -> { - val matchedClass = - srg.classes.firstOrNull { it.getName("intermediary") == methodMatch.groups[1]!!.value } - val replacementName: String = srg.classes.asSequence() - .flatMap { it.methods.asSequence() } - .filter { it.getName("intermediary") == methodMatch.groups[2]!!.value } - .firstOrNull { it.getDescriptor("intermediary") == methodMatch.groups[3]!!.value } - ?.getName("srg") ?: methodMatch.groups[2]!!.value - obj.addProperty( - key, originalRef - .replaceFirst( - methodMatch.groups[1]!!.value, - matchedClass?.getName("srg") ?: methodMatch.groups[1]!!.value - ) - .replaceFirst(methodMatch.groups[2]!!.value, replacementName) - .replaceFirst(methodMatch.groups[3]!!.value, methodMatch.groups[3]!!.value.remapDescriptor { - srg.classes.firstOrNull { def -> def.getName("intermediary") == it }?.getName("srg") - ?: it - }) - ) - } - fieldMatch != null -> { - val matchedClass = - srg.classes.firstOrNull { it.getName("intermediary") == fieldMatch.groups[1]!!.value } - val replacementName: String = srg.classes.asSequence() - .flatMap { it.fields.asSequence() } - .filter { it.getName("intermediary") == fieldMatch.groups[2]!!.value } - .firstOrNull { it.getDescriptor("intermediary") == fieldMatch.groups[3]!!.value } - ?.getName("srg") ?: fieldMatch.groups[2]!!.value - obj.addProperty( - key, originalRef - .replaceFirst( - fieldMatch.groups[1]!!.value, - matchedClass?.getName("srg") ?: fieldMatch.groups[1]!!.value - ) - .replaceFirst(fieldMatch.groups[2]!!.value, replacementName) - .replaceFirst(fieldMatch.groups[3]!!.value, fieldMatch.groups[3]!!.value.remapDescriptor { - srg.classes.firstOrNull { def -> def.getName("intermediary") == it }?.getName("srg") - ?: it - }) - ) - } - fieldMatchWithoutClass != null -> { - val replacementName: String = srg.classes.asSequence() - .flatMap { it.fields.asSequence() } - .filter { it.getName("intermediary") == fieldMatchWithoutClass.groups[1]!!.value } - .firstOrNull { it.getDescriptor("intermediary") == fieldMatchWithoutClass.groups[2]!!.value } - ?.getName("srg") ?: fieldMatchWithoutClass.groups[1]!!.value - obj.addProperty( - key, originalRef - .replaceFirst(fieldMatchWithoutClass.groups[1]!!.value, replacementName) - .replaceFirst(fieldMatchWithoutClass.groups[2]!!.value, fieldMatchWithoutClass.groups[2]!!.value.remapDescriptor { - srg.classes.firstOrNull { def -> def.getName("intermediary") == it }?.getName("srg") - ?: it - }) - ) - } - methodMatchWithoutClass != null -> { - val replacementName: String = srg.classes.asSequence() - .flatMap { it.methods.asSequence() } - .filter { it.getName("intermediary") == methodMatchWithoutClass.groups[1]!!.value } - .firstOrNull { it.getDescriptor("intermediary") == methodMatchWithoutClass.groups[2]!!.value } - ?.getName("srg") ?: methodMatchWithoutClass.groups[1]!!.value - obj.addProperty( - key, originalRef - .replaceFirst(methodMatchWithoutClass.groups[1]!!.value, replacementName) - .replaceFirst( - methodMatchWithoutClass.groups[2]!!.value, - methodMatchWithoutClass.groups[2]!!.value.remapDescriptor { - srg.classes.firstOrNull { def -> def.getName("intermediary") == it }?.getName("srg") - ?: it - }) - ) - } - classMatch != null -> obj.addProperty(key, classMatch.getName("srg")) - else -> project.logger.warn("Failed to remap refmap value: $originalRef") - } - } - } - - private fun String.remapDescriptor(classMappings: (String) -> String): String { - return try { - val reader = StringReader(this) - val result = StringBuilder() - var insideClassName = false - val className = StringBuilder() - while (true) { - val c: Int = reader.read() - if (c == -1) { - break - } - if (c == ';'.toInt()) { - insideClassName = false - result.append(classMappings(className.toString())) - } - if (insideClassName) { - className.append(c.toChar()) - } else { - result.append(c.toChar()) - } - if (!insideClassName && c == 'L'.toInt()) { - insideClassName = true - className.setLength(0) - } - } - result.toString() - } catch (e: IOException) { - throw AssertionError(e) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeFabricModJson.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeFabricModJson.kt deleted file mode 100644 index 0d467c9..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeFabricModJson.kt +++ /dev/null @@ -1,31 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.Transformer -import org.gradle.api.Project -import org.zeroturnaround.zip.ByteSource -import org.zeroturnaround.zip.ZipUtil -import java.nio.file.Files -import java.nio.file.Path -import java.util.* - -object GenerateFakeFabricModJson : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - Files.copy(input, output) - val fakeModId = "generated_" + UUID.randomUUID().toString().filterNot { it == '-' }.take(7) - ZipUtil.addOrReplaceEntries( - output.toFile(), arrayOf( - ByteSource( - "fabric.mod.json", """{ - "schemaVersion": 1, - "id": "$fakeModId", - "name": "Generated Mod (Please Ignore)", - "version": "1.0.0", - "custom": { - "fabric-loom:generated": true - } -}""".toByteArray() - ) - ) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeForgeMod.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeForgeMod.kt deleted file mode 100644 index 382d091..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/GenerateFakeForgeMod.kt +++ /dev/null @@ -1,52 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.Transformer -import org.gradle.api.Project -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.Opcodes -import org.zeroturnaround.zip.ByteSource -import org.zeroturnaround.zip.ZipUtil -import java.nio.file.Files -import java.nio.file.Path -import java.util.* - -object GenerateFakeForgeMod : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - val fakeModId = "generated_" + UUID.randomUUID().toString().filterNot { it == '-' }.take(7) - Files.copy(input, output) - ZipUtil.addEntries( - output.toFile(), arrayOf( - ByteSource( - "META-INF/mods.toml", - """modLoader = "javafml" - loaderVersion = "[33,)" - license = "Generated" - [[mods]] - modId = "$fakeModId"""".toByteArray() - ), - ByteSource( - "pack.mcmeta", - """{"pack":{"description":"Generated","pack_format":4}}""".toByteArray() - ), - ByteSource( - "generated/$fakeModId.class", - ClassWriter(0).let { classWriter -> - classWriter.visit(52, Opcodes.ACC_PUBLIC, "generated/$fakeModId", null, "java/lang/Object", null) - val modAnnotation = classWriter.visitAnnotation("Lnet/minecraftforge/fml/common/Mod;", false) - modAnnotation.visit("value", fakeModId) - modAnnotation.visitEnd() - classWriter.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, arrayOf()).also { - it.visitVarInsn(Opcodes.ALOAD, 0) - it.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false) - it.visitInsn(Opcodes.RETURN) - it.visitMaxs(1, 1) - it.visitEnd() - } - classWriter.visitEnd() - classWriter.toByteArray() - } - ) - ) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemapMixinVariables.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemapMixinVariables.kt index b1dfea4..9a23a01 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemapMixinVariables.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemapMixinVariables.kt @@ -1,65 +1,21 @@ package me.shedaniel.architect.plugin.transformers -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.TransformerStepSkipped -import me.shedaniel.architect.plugin.utils.validateJarFs +import me.shedaniel.architectury.transformer.shadowed.impl.net.fabricmc.tinyremapper.IMappingProvider +import me.shedaniel.architectury.transformer.shadowed.impl.net.fabricmc.tinyremapper.TinyUtils +import me.shedaniel.architectury.transformer.transformers.base.TinyRemapperTransformer import net.fabricmc.loom.LoomGradleExtension -import net.fabricmc.loom.util.LoggerFilter -import net.fabricmc.tinyremapper.OutputConsumerPath -import net.fabricmc.tinyremapper.TinyRemapper -import net.fabricmc.tinyremapper.TinyUtils import org.gradle.api.Project import java.io.File -import java.nio.file.Files -import java.nio.file.Path -object RemapMixinVariables : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { +class RemapMixinVariables(private val project: Project) : TinyRemapperTransformer { + override fun collectMappings(): MutableList { val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java) - var remapperBuilder = TinyRemapper.newRemapper() - var requiresRemap = false - for (mixinMapFile in loomExtension.allMixinMappings) { - if (mixinMapFile.exists()) { - if (!requiresRemap) { - requiresRemap = Files.readAllLines(mixinMapFile.toPath()).count { it.isNotBlank() } > 1 - } - remapperBuilder = remapperBuilder.withMappings( - TinyUtils.createTinyMappingProvider( - mixinMapFile.toPath(), - "named", - "intermediary" - ) - ) - } - } - - if (!requiresRemap) { - Files.copy(input, output) - throw TransformerStepSkipped - } - - val remapper = remapperBuilder.build() - - val classpathFiles: Set = LinkedHashSet( - project.configurations.getByName("compileClasspath").files - ) - val classpath = classpathFiles.asSequence().map { obj: File -> obj.toPath() }.filter { p: Path -> - input != p && Files.exists(p) - }.toList().toTypedArray() - - LoggerFilter.replaceSystemOut() - try { - project.validateJarFs(output) - OutputConsumerPath.Builder(output).build().use { outputConsumer -> - outputConsumer.addNonClassFiles(input) - remapper.readClassPath(*classpath) - remapper.readInputs(input) - remapper.apply(outputConsumer) - } - } catch (e: Exception) { - throw RuntimeException("Failed to remap $input to $output", e) - } finally { - remapper.finish() - } + return loomExtension.allMixinMappings.asSequence().filter(File::exists).map { + TinyUtils.createTinyMappingProvider( + it.toPath(), + "named", + "intermediary" + ) + }.toMutableList() } } \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemoveFabricModJson.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemoveFabricModJson.kt deleted file mode 100644 index e4294d4..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/RemoveFabricModJson.kt +++ /dev/null @@ -1,19 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.TransformerStepSkipped -import org.gradle.api.Project -import org.zeroturnaround.zip.ZipUtil -import java.nio.file.Files -import java.nio.file.Path - -object RemoveFabricModJson : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - Files.copy(input, output) - if (ZipUtil.containsEntry(output.toFile(), "fabric.mod.json")) { - ZipUtil.removeEntry(output.toFile(), "fabric.mod.json") - } else { - throw TransformerStepSkipped - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformExpectPlatform.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformExpectPlatform.kt deleted file mode 100644 index f2769f8..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformExpectPlatform.kt +++ /dev/null @@ -1,206 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.ArchitectPluginExtension -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.projectUniqueIdentifier -import me.shedaniel.architect.plugin.utils.ClassTransformer -import me.shedaniel.architect.plugin.utils.Transform -import org.gradle.api.Project -import org.objectweb.asm.ClassReader -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.Handle -import org.objectweb.asm.Opcodes -import org.objectweb.asm.commons.ClassRemapper -import org.objectweb.asm.commons.Remapper -import org.objectweb.asm.tree.* -import org.zeroturnaround.zip.ZipUtil -import java.io.InputStream -import java.lang.invoke.CallSite -import java.lang.invoke.MethodHandles -import java.lang.invoke.MethodType -import java.nio.file.Path -import java.util.zip.ZipEntry - -object TransformExpectPlatform : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - Transform.transform(input, output, transformExpectPlatform(project)) - } - - fun transformExpectPlatform(project: Project): ClassTransformer { - val projectUniqueIdentifier by lazy { project.projectUniqueIdentifier() } - var injectedClass = !project.extensions.getByType(ArchitectPluginExtension::class.java).injectInjectables - return { clazz, classAdder -> - if (!injectedClass) { - injectedClass = true - Transform::class.java.getResourceAsStream("/annotations-inject/injection.jar").use { stream -> - ZipUtil.iterate(stream) { input: InputStream, entry: ZipEntry -> - if (entry.name.endsWith(".class")) { - val newName = "$projectUniqueIdentifier/${ - entry.name.substringBeforeLast(".class").substringAfterLast('/') - }" - classAdder(newName, input.readBytes().let { - val node = ClassNode(Opcodes.ASM8) - ClassReader(it).accept(node, ClassReader.EXPAND_FRAMES) - val writer = ClassWriter(ClassWriter.COMPUTE_MAXS) - val remapper = ClassRemapper(writer, object : Remapper() { - override fun map(internalName: String?): String { - if (internalName?.startsWith("me/shedaniel/architect/plugin/callsite") == true) { - return internalName.replace( - "me/shedaniel/architect/plugin/callsite", - projectUniqueIdentifier - ) - } - return super.map(internalName) - } - }) - node.apply { - name = newName - }.accept(remapper) - - writer.toByteArray() - }) - } - } - } - } - - clazz.methods.mapNotNull { method -> - when { - method?.visibleAnnotations?.any { it.desc == TransformInjectables.expectPlatform } == true -> method to "me/shedaniel/architectury/PlatformMethods" - method?.invisibleAnnotations?.any { it.desc == TransformInjectables.expectPlatformNew } == true -> { - method to "$projectUniqueIdentifier/PlatformMethods" - } - else -> null - } - }.forEach { (method, platformMethodsClass) -> - if (method.access and Opcodes.ACC_STATIC == 0) { - System.err.println("@ExpectPlatform can only apply to static methods!") - } else { - method.instructions.clear() - val endOfDesc = method.desc.lastIndexOf(')') - val returnValue = method.desc.substring(endOfDesc + 1) - val args = method.desc.substring(1, endOfDesc) - var cursor = 0 - var inClass = false - var index = 0 - while (cursor < args.length) { - val char = args[cursor] - if (inClass) { - if (char == ';') { - method.instructions.addLoad(char, index++) - inClass = false - } - } else when (char) { - '[' -> Unit - 'L' -> inClass = true - else -> method.instructions.addLoad(char, when (char) { - 'J', 'D' -> index.also { index += 2 } - else -> index++ - }) - } - cursor++ - } - - val methodType = MethodType.methodType( - CallSite::class.java, - MethodHandles.Lookup::class.java, - String::class.java, - MethodType::class.java - ) - - val handle = Handle( - Opcodes.H_INVOKESTATIC, - platformMethodsClass, - "platform", - methodType.toMethodDescriptorString(), - false - ) - - method.instructions.add( - InvokeDynamicInsnNode( - method.name, - method.desc, - handle - ) - ) - - method.instructions.addReturn(returnValue.first { it != '[' }) - method.maxStack = -1 - } - } - - clazz - } - } - - private fun InsnList.addLoad(type: Char, index: Int) { - when (type) { - ';' -> add( - VarInsnNode( - Opcodes.ALOAD, - index - ) - ) - 'I', 'S', 'B', 'C', 'Z' -> add( - VarInsnNode( - Opcodes.ILOAD, - index - ) - ) - 'F' -> add( - VarInsnNode( - Opcodes.FLOAD, - index - ) - ) - 'J' -> add( - VarInsnNode( - Opcodes.LLOAD, - index - ) - ) - 'D' -> add( - VarInsnNode( - Opcodes.DLOAD, - index - ) - ) - else -> throw IllegalStateException("Invalid Type: $type") - } - } - - private fun InsnList.addReturn(type: Char) { - when (type) { - 'L' -> add( - InsnNode( - Opcodes.ARETURN - ) - ) - 'I', 'S', 'B', 'C', 'Z' -> add( - InsnNode( - Opcodes.IRETURN - ) - ) - 'F' -> add( - InsnNode( - Opcodes.FRETURN - ) - ) - 'J' -> add( - InsnNode( - Opcodes.LRETURN - ) - ) - 'D' -> add( - InsnNode( - Opcodes.DRETURN - ) - ) - 'V' -> add( - InsnNode( - Opcodes.RETURN - ) - ) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeBytecode.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeBytecode.kt deleted file mode 100644 index 53f7fe7..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeBytecode.kt +++ /dev/null @@ -1,72 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.utils.Transform -import org.gradle.api.Project -import org.objectweb.asm.Opcodes -import org.objectweb.asm.tree.AnnotationNode -import org.objectweb.asm.tree.MethodInsnNode -import java.nio.file.Path - -object TransformForgeBytecode : Transformer { - val forgeEvent = "Lme/shedaniel/architectury/ForgeEvent;" - val forgeEventCancellable = "Lme/shedaniel/architectury/ForgeEventCancellable;" - val cancellable = "Lnet/minecraftforge/eventbus/api/Cancelable;" - - private val environmentClass = "net/fabricmc/api/Environment" - - override fun invoke(project: Project, input: Path, output: Path) { - Transform.transform(input, output) { node, classAdder -> - if (node.access and Opcodes.ACC_INTERFACE == 0) { - if (node.visibleAnnotations?.any { it.desc == forgeEvent || it.desc == forgeEventCancellable } == true) { - node.superName = "net/minecraftforge/eventbus/api/Event" - node.methods.forEach { - if (it.name == "") { - for (insnNode in it.instructions) { - if (insnNode.opcode == Opcodes.INVOKESPECIAL) { - insnNode as MethodInsnNode - if (insnNode.name == "" && insnNode.owner == "java/lang/Object") { - insnNode.owner = "net/minecraftforge/eventbus/api/Event" - break - } - } - } - } - } - node.signature?.let { - node.signature = it.substringBeforeLast('L') + "Lnet/minecraftforge/eventbus/api/Event;" - } - // if @ForgeEventCancellable, add the cancellable annotation from forge - node.visibleAnnotations.apply { - if (any { it.desc == forgeEventCancellable }) { - add(AnnotationNode(cancellable)) - } - } - } - } - node.visibleAnnotations = (node.visibleAnnotations ?: mutableListOf()).apply { - val invisibleEnvironments = - node.invisibleAnnotations?.filter { it.desc == "L${environmentClass};" } ?: emptyList() - node.invisibleAnnotations?.removeAll(invisibleEnvironments) - addAll(invisibleEnvironments) - } - node.fields.forEach { field -> - field.visibleAnnotations = (field.visibleAnnotations ?: mutableListOf()).apply { - val invisibleEnvironments = - field.invisibleAnnotations?.filter { it.desc == "L${environmentClass};" } ?: emptyList() - field.invisibleAnnotations?.removeAll(invisibleEnvironments) - addAll(invisibleEnvironments) - } - } - node.methods.forEach { method -> - method.visibleAnnotations = (method.visibleAnnotations ?: mutableListOf()).apply { - val invisibleEnvironments = - method.invisibleAnnotations?.filter { it.desc == "L${environmentClass};" } ?: emptyList() - method.invisibleAnnotations?.removeAll(invisibleEnvironments) - addAll(invisibleEnvironments) - } - } - node - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeEnvironment.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeEnvironment.kt deleted file mode 100644 index 6fbb50b..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformForgeEnvironment.kt +++ /dev/null @@ -1,104 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.TransformerStepSkipped -import me.shedaniel.architect.plugin.utils.validateJarFs -import net.fabricmc.loom.LoomGradleExtension -import net.fabricmc.loom.util.LoggerFilter -import net.fabricmc.tinyremapper.* -import org.gradle.api.Project -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.Opcodes -import java.io.File -import java.nio.file.Files -import java.nio.file.Path - -object TransformForgeEnvironment : Transformer { - override fun invoke(project: Project, input: Path, output: Path) { - val remapperBuilder: TinyRemapper.Builder = TinyRemapper.newRemapper() - .withMappings(remapEnvironment()) - .skipLocalVariableMapping(true) - - mapMixin(project, remapperBuilder) - - val classpathFiles: Set = LinkedHashSet( - project.configurations.getByName("compileClasspath").files - ) - val classpath = classpathFiles.asSequence().map { obj: File -> obj.toPath() } - .filter { p: Path -> input != p && Files.exists(p) }.toList().toTypedArray() - val remapper = remapperBuilder.build() - - LoggerFilter.replaceSystemOut() - try { - project.validateJarFs(output) - OutputConsumerPath.Builder(output).build().use { outputConsumer -> - outputConsumer.addNonClassFiles(input, NonClassCopyMode.FIX_META_INF, null) - remapper.readClassPath(*classpath) - remapper.readInputs(input) - remapper.apply(outputConsumer) - } - } catch (e: Exception) { - throw RuntimeException("Failed to remap $input to $output", e) - } finally { - remapper.finish() - } - } - - private fun remapEnvironment(): IMappingProvider = IMappingProvider { out -> - out.acceptClass("net/fabricmc/api/Environment", "net/minecraftforge/api/distmarker/OnlyIn") - out.acceptClass("net/fabricmc/api/EnvType", "net/minecraftforge/api/distmarker/Dist") - out.acceptField( - IMappingProvider.Member("net/fabricmc/api/EnvType", "SERVER", "Lnet/fabricmc/api/EnvType;"), - "DEDICATED_SERVER" - ) - } - - private fun mapMixin(project: Project, remapperBuilder: TinyRemapper.Builder) { - val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java) - val srg = project.extensions.getByType(LoomGradleExtension::class.java).mappingsProvider.mappingsWithSrg - for (mixinMapFile in loomExtension.allMixinMappings) { - if (mixinMapFile.exists()) { - remapperBuilder.withMappings { sink -> - TinyUtils.createTinyMappingProvider(mixinMapFile.toPath(), "named", "intermediary").load(object : - IMappingProvider.MappingAcceptor { - override fun acceptClass(srcName: String, dstName: String) { - sink.acceptClass(dstName, srg.classes - .firstOrNull { it.getName("intermediary") == dstName } - ?.getName("srg") ?: dstName - ) - } - - override fun acceptMethod(method: IMappingProvider.Member, dstName: String) { - sink.acceptMethod( - IMappingProvider.Member(method.owner, dstName, method.desc), - srg.classes - .flatMap { it.methods } - .firstOrNull { it.getName("intermediary") == dstName } - ?.getName("srg") ?: dstName) - } - - override fun acceptField(field: IMappingProvider.Member, dstName: String) { - sink.acceptField( - IMappingProvider.Member(field.owner, dstName, field.desc), - srg.classes - .flatMap { it.fields } - .firstOrNull { it.getName("intermediary") == dstName } - ?.getName("srg") ?: dstName) - } - - override fun acceptMethodArg(method: IMappingProvider.Member, lvIndex: Int, dstName: String) {} - - override fun acceptMethodVar( - method: IMappingProvider.Member, - lvIndex: Int, - startOpIdx: Int, - asmIndex: Int, - dstName: String - ) { - } - }) - } - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformInjectables.kt b/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformInjectables.kt deleted file mode 100644 index c36dcd9..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/transformers/TransformInjectables.kt +++ /dev/null @@ -1,69 +0,0 @@ -package me.shedaniel.architect.plugin.transformers - -import me.shedaniel.architect.plugin.ArchitectPluginExtension -import me.shedaniel.architect.plugin.Transformer -import me.shedaniel.architect.plugin.TransformerStepSkipped -import me.shedaniel.architect.plugin.projectUniqueIdentifier -import me.shedaniel.architect.plugin.utils.validateJarFs -import net.fabricmc.loom.util.LoggerFilter -import net.fabricmc.tinyremapper.IMappingProvider -import net.fabricmc.tinyremapper.NonClassCopyMode -import net.fabricmc.tinyremapper.OutputConsumerPath -import net.fabricmc.tinyremapper.TinyRemapper -import org.gradle.api.Project -import java.io.File -import java.nio.file.Files -import java.nio.file.Path - -object TransformInjectables : Transformer { - const val expectPlatform = "Lme/shedaniel/architectury/ExpectPlatform;" - const val expectPlatformNew = "Lme/shedaniel/architectury/annotations/ExpectPlatform;" - - override fun invoke(project: Project, input: Path, output: Path) { - if (project.extensions.getByType(ArchitectPluginExtension::class.java).injectInjectables) { - transformArchitecturyInjectables(project, input, output) - } else { - Files.copy(input, output) - throw TransformerStepSkipped - } - } - - private fun transformArchitecturyInjectables(project: Project, input: Path, output: Path) { - val remapper = TinyRemapper.newRemapper() - .withMappings { sink -> - sink.acceptClass( - "me/shedaniel/architectury/targets/ArchitecturyTarget", - project.projectUniqueIdentifier() + "/PlatformMethods" - ) - sink.acceptMethod( - IMappingProvider.Member( - "me/shedaniel/architectury/targets/ArchitecturyTarget", - "getCurrentTarget", - "()Ljava/lang/String;" - ), "getModLoader" - ) - } - .build() - - val classpathFiles: Set = LinkedHashSet( - project.configurations.getByName("compileClasspath").files - ) - val classpath = classpathFiles.asSequence().map { obj: File -> obj.toPath() } - .filter { p: Path -> Files.exists(p) }.toList().toTypedArray() - - LoggerFilter.replaceSystemOut() - try { - project.validateJarFs(output) - OutputConsumerPath.Builder(output).build().use { outputConsumer -> - outputConsumer.addNonClassFiles(input, NonClassCopyMode.UNCHANGED, null) - remapper.readClassPath(*classpath) - remapper.readInputs(input) - remapper.apply(outputConsumer) - } - } catch (e: Exception) { - throw RuntimeException("Failed to remap $input to $output", e) - } finally { - remapper.finish() - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/utils/FileSystemUtils.kt b/src/main/kotlin/me/shedaniel/architect/plugin/utils/FileSystemUtils.kt deleted file mode 100644 index 470ff0e..0000000 --- a/src/main/kotlin/me/shedaniel/architect/plugin/utils/FileSystemUtils.kt +++ /dev/null @@ -1,25 +0,0 @@ -package me.shedaniel.architect.plugin.utils - -import org.gradle.api.Project -import java.net.URI -import java.nio.file.FileSystemNotFoundException -import java.nio.file.Path -import java.nio.file.ProviderNotFoundException -import java.nio.file.spi.FileSystemProvider - -fun Project.validateJarFs(path: Path) { - val uri = URI("jar:" + path.toUri().toString()) - val provider = FileSystemProvider.installedProviders().firstOrNull { it.scheme == uri.scheme } - ?: throw ProviderNotFoundException("Provider \"${uri.scheme}\" not found") - try { - val fs = provider.getFileSystem(uri) - val cl = fs.javaClass.classLoader - if (fs.isOpen) { - logger.error("Detected open FS on $path! Forcefully closing the FS! The FS is created on $cl!") - fs.close() - } - } catch (ignored: FileSystemNotFoundException) { - } catch (e: Exception) { - e.printStackTrace() - } -} \ No newline at end of file