diff --git a/src/annotationsInject/java/me/shedaniel/architect/plugin/callsite/PlatformMethods.java b/src/annotationsInject/java/me/shedaniel/architect/plugin/callsite/PlatformMethods.java index 60307e9..61d1918 100644 --- a/src/annotationsInject/java/me/shedaniel/architect/plugin/callsite/PlatformMethods.java +++ b/src/annotationsInject/java/me/shedaniel/architect/plugin/callsite/PlatformMethods.java @@ -36,28 +36,28 @@ public class PlatformMethods { private static String modLoader = null; public static String getModLoader() { - try { - return (String) Class.forName("me.shedaniel.architectury.platform.Platform").getDeclaredMethod("getModLoader").invoke(null); - } catch (Throwable ignored) { - } if (modLoader == null) { - List loader = new ArrayList<>(); - HashMap MOD_LOADERS = new HashMap<>(); - MOD_LOADERS.put("net.fabricmc.loader.FabricLoader", "fabric"); - MOD_LOADERS.put("net.minecraftforge.fml.common.Mod", "forge"); - for (Map.Entry entry : MOD_LOADERS.entrySet()) { - try { - Class.forName(entry.getKey(), false, null); - loader.add(entry.getValue()); - break; - } catch (ClassNotFoundException ignored) { + try { + modLoader = (String) Class.forName("me.shedaniel.architectury.platform.Platform").getDeclaredMethod("getModLoader").invoke(null); + } catch (Throwable ignored) { + List loader = new ArrayList<>(); + HashMap MOD_LOADERS = new HashMap<>(); + MOD_LOADERS.put("net.fabricmc.loader.FabricLoader", "fabric"); + MOD_LOADERS.put("net.minecraftforge.fml.common.Mod", "forge"); + for (Map.Entry entry : MOD_LOADERS.entrySet()) { + try { + Class.forName(entry.getKey(), false, null); + loader.add(entry.getValue()); + break; + } catch (ClassNotFoundException ignored1) { + } } + if (loader.isEmpty()) + throw new IllegalStateException("No detected mod loader!"); + if (loader.size() >= 2) + System.err.println("Detected multiple mod loaders! Something is wrong on the classpath! " + String.join(", ", loader)); + modLoader = loader.get(0); } - if (loader.isEmpty()) - throw new IllegalStateException("No detected mod loader!"); - if (loader.size() >= 2) - System.err.println("Detected multiple mod loaders! Something is wrong on the classpath! " + String.join(", ", loader)); - modLoader = loader.get(0); } return modLoader; } diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt b/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt index 179be0d..1d1a199 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/ArchitectPluginExtension.kt @@ -9,6 +9,7 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask open class ArchitectPluginExtension(val project: Project) { var minecraft = "" + var injectInjectables = true fun common() { common(true) @@ -21,8 +22,10 @@ open class ArchitectPluginExtension(val project: Project) { } fun common(forgeEnabled: Boolean) { - with(project.dependencies) { - add("compileOnly", "me.shedaniel:architectury-annotations:+") + if (injectInjectables) { + with(project.dependencies) { + add("compileOnly", "me.shedaniel:architectury-injectables:1.0.4") + } } if (forgeEnabled) { diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/TransformExpect.kt b/src/main/kotlin/me/shedaniel/architect/plugin/TransformExpect.kt index 722a23d..6f49cc8 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/TransformExpect.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/TransformExpect.kt @@ -41,46 +41,46 @@ fun Project.projectUniqueIdentifier(): String { fun transformExpectPlatform(project: Project): ClassTransformer { val projectUniqueIdentifier by lazy { project.projectUniqueIdentifier() } - var injectedClass = false + 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 == expectPlatform } == true -> method to "me/shedaniel/architectury/PlatformMethods" method?.invisibleAnnotations?.any { it.desc == expectPlatformNew } == true -> { - 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() - }) - } - } - } - } - method to "$projectUniqueIdentifier/PlatformMethods" } else -> null diff --git a/src/main/kotlin/me/shedaniel/architect/plugin/TransformTask.kt b/src/main/kotlin/me/shedaniel/architect/plugin/TransformTask.kt index f01f285..7c92bc6 100644 --- a/src/main/kotlin/me/shedaniel/architect/plugin/TransformTask.kt +++ b/src/main/kotlin/me/shedaniel/architect/plugin/TransformTask.kt @@ -7,12 +7,12 @@ import me.shedaniel.architect.plugin.utils.Transform import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.util.LoggerFilter import net.fabricmc.loom.util.MixinRefmapHelper -import net.fabricmc.tinyremapper.OutputConsumerPath -import net.fabricmc.tinyremapper.TinyRemapper -import net.fabricmc.tinyremapper.TinyUtils +import net.fabricmc.tinyremapper.* import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.TaskAction import org.gradle.jvm.tasks.Jar +import org.objectweb.asm.ClassWriter +import org.objectweb.asm.Opcodes import java.io.File import java.nio.file.Files import java.nio.file.Path @@ -25,6 +25,7 @@ open class TransformTask : Jar() { fun doTask() { val input: Path = this.input.asFile.get().toPath() val intermediate: Path = input.parent.resolve(input.toFile().nameWithoutExtension + "-intermediate.jar") + val intermediate2: Path = input.parent.resolve(input.toFile().nameWithoutExtension + "-intermediate2.jar") val output: Path = this.archiveFile.get().asFile.toPath() if (addRefmap) { @@ -69,11 +70,20 @@ open class TransformTask : Jar() { Files.copy(input, intermediate) } + Files.deleteIfExists(intermediate2) project.logger.lifecycle(":transforming " + input.fileName + " => " + intermediate.fileName) - Transform.transform(intermediate, output, transformExpectPlatform(project)) + Transform.transform(intermediate, intermediate2, transformExpectPlatform(project)) Files.deleteIfExists(intermediate) + if (project.extensions.getByType(ArchitectPluginExtension::class.java).injectInjectables) { + transformArchitecturyInjectables(intermediate2, output) + } else { + Files.copy(intermediate2, output) + } + + Files.deleteIfExists(intermediate2) + if (addRefmap) { val loomExtension = project.extensions.getByType(LoomGradleExtension::class.java) if (MixinRefmapHelper.addRefmapName( @@ -86,4 +96,35 @@ open class TransformTask : Jar() { } } } + + private fun transformArchitecturyInjectables(intermediate2: 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 -> this.input.asFile.get().toPath() != p && Files.exists(p) }.toList().toTypedArray() + + try { + OutputConsumerPath.Builder(output).build().use { outputConsumer -> + outputConsumer.addNonClassFiles(intermediate2, NonClassCopyMode.UNCHANGED, null) + remapper.readClassPath(*classpath) + remapper.readInputs(intermediate2) + remapper.apply(outputConsumer) + } + } catch (e: Exception) { + remapper.finish() + throw RuntimeException("Failed to remap $intermediate2 to $output", e) + } + } } \ No newline at end of file