//file:noinspection UnnecessaryQualifiedReference buildscript { repositories { maven { url "https://maven.architectury.dev/" } mavenCentral() mavenLocal() } dependencies { classpath "com.guardsquare:proguard-gradle:7.2.1" classpath "dev.architectury:architectury-transformer:5.2.9999" } } plugins { id("architectury-plugin") version("3.4-SNAPSHOT") id("dev.architectury.loom") version("0.12.0-SNAPSHOT") apply false id("org.cadixdev.licenser") version("0.6.1") id("me.shedaniel.unified-publishing") version("0.1.+") id("maven-publish") } import java.text.SimpleDateFormat def runNumber = System.getenv("GITHUB_RUN_NUMBER") ?: "9999" version = rootProject.base_version + "." + runNumber + (rootProject.unstable.toBoolean() ? "-alpha" : "") group = "me.shedaniel" subprojects { apply plugin: "me.shedaniel.unified-publishing" apply plugin: "java" apply plugin: "dev.architectury.loom" sourceCompatibility = targetCompatibility = 1.8 java { withSourcesJar() } loom { silentMojangMappingsLicense() } dependencies { minecraft("com.mojang:minecraft:${rootProject.minecraft_version}") mappings(loom.layered { officialMojangMappings() parchment("org.parchmentmc.data:parchment-1.17.1:2021.10.10@zip") crane("dev.architectury:crane:1.17+build.11") }) } jar { from rootProject.file("LICENSE") } tasks.withType(JavaCompile) { options.encoding = "UTF-8" options.release = 17 } } subprojects { if (project.path == ':fabric' || project.path == ':forge') { loom { mods { main { // to match the default mod generated for Forge sourceSet project.sourceSets.main def depProjects = [":api", ":runtime", ":default-plugin"] depProjects.each { sourceSet project(it).sourceSets.main } } } } } } allprojects { apply plugin: "maven-publish" apply plugin: "architectury-plugin" apply plugin: "org.cadixdev.licenser" architectury { compileOnly() } repositories { maven { url "https://maven.shedaniel.me" } maven { url "https://maven.parchmentmc.org" } maven { url "https://maven.terraformersmc.com/releases" } } license { header rootProject.file("HEADER") include "**/*.java" exclude "mezz/jei/api/**/*.java" ext { name = "shedaniel" year = "2018, 2019, 2020, 2021, 2022" } } tasks.withType(GenerateModuleMetadata) { enabled = false } } ["api", "default-plugin", "runtime"].forEach { project(":fabric").evaluationDependsOn(":$it") } subprojects { group = rootProject.group version = rootProject.version archivesBaseName = rootProject.name publishing { repositories { if (System.getenv("MAVEN_PASS") != null) { maven { url = "https://deploy.shedaniel.me/" credentials { username = "shedaniel" password = System.getenv("MAVEN_PASS") } } } } } } task licenseFormatAll subprojects { licenseFormatAll.dependsOn("${path}:licenseFormat") } ext { releaseChangelog = "No changelog" } /* Thank you modmenu & fablabs */ task releaseOnCf { def df = new SimpleDateFormat("yyyy-MM-dd HH:mm") df.setTimeZone(TimeZone.getTimeZone("UTC")) def branch if (System.env.BRANCH_NAME) { branch = System.env.BRANCH_NAME branch = branch.substring(branch.lastIndexOf("/") + 1) } else { branch = "git rev-parse --abbrev-ref HEAD".execute().in.text.trim() } if (branch == "HEAD") { branch = "git rev-parse --short HEAD".execute().in.text.trim() } def time = df.format(new Date()) def changes = new StringBuilder() changes << "## REI v$project.version for $project.supported_version\nUpdated at **$time**.\n![Click here for changelog](https://www.github.com/shedaniel/RoughlyEnoughItems/commits/$branch)" def proc = "git log --max-count=200 --pretty=format:%s".execute() proc.in.eachLine { line -> def processedLine = line.toString() if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) { changes << "\n- ${processedLine.capitalize()}" } } proc.waitFor() releaseChangelog = changes.toString() if (subprojects.any { it.name == "forge" }) { dependsOn project("forge").tasks.getByName("publishUnified") } if (subprojects.any { it.name == "fabric" }) { dependsOn project("fabric").tasks.getByName("publishUnified") } } def randomString(len) { def AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" def rnd = new java.security.SecureRandom() return (0..len).toList().collect { AB.charAt(rnd.nextInt(AB.length())) }.join("") } rootProject.file(".gradle/proguard-dictionary.txt").delete() rootProject.file(".gradle/proguard-dictionary.txt").write((0..1000).toList().collect { randomString(10) }.join("\n")) ["fabric", "forge"].each { loader -> project(":$loader") { afterEvaluate { def proguardJarOut = file(tasks.getByName("shadowJar").archiveFile.get().getAsFile().absolutePath.replace(".jar", "-min.jar")) task proguardJar(type: proguard.gradle.ProGuardTask, dependsOn: ["shadowJar"]) { doFirst { if (proguardJarOut.exists()) { proguardJarOut.delete() } } verbose() injars tasks.getByName("shadowJar").archiveFile.get().getAsFile() outjars proguardJarOut libraryjars files(configurations.compileClasspath) libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class' dontshrink() keep "class me.shedaniel.rei.api.** { *; }" keep "class me.shedaniel.rei.plugin.** { *; }" keepclassmembers "class * { void onInitialize(); void onInitializeClient(); }" keepclassmembers "class * { @net.minecraft.obfuscate.DontObfuscate ; @net.minecraft.obfuscate.DontObfuscate ; }" keepclassmembers "class me.shedaniel.rei.impl.*Internals { ; }" keepclassmembers "class me.shedaniel.rei.impl.client.config.ConfigObjectImpl* { ; }" dontwarn "me.shedaniel.rei.impl.init.RoughlyEnoughItemsInitializer" dontwarn "me.shedaniel.rei.plugin.client.DefaultClientPlugin" obfuscationdictionary rootProject.file(".gradle/proguard-dictionary.txt") classobfuscationdictionary rootProject.file(".gradle/proguard-dictionary.txt") repackageclasses "me.shedaniel.rei.impl.${randomString(10)}" keep "class me.shedaniel.rei.mixin.$loader.** { *; }" keepattributes "Signature,SourceFile,LineNumberTable,Exceptions,InnerClasses,*Annotation*" printmapping file(".gradle/proguard-mapping.txt") optimizationpasses 5 optimizations "**" allowaccessmodification() doLast { try (def access = dev.architectury.transformer.input.OpenedFileAccess.ofJar(proguardJarOut.toPath())) { dev.architectury.transformer.Transform.runTransformers( new dev.architectury.transformer.transformers.base.edit.SimpleTransformerContext(args -> { throw new IllegalStateException(); }, true, false, true), dev.architectury.transformer.transformers.ClasspathProvider.of(files(configurations.compileClasspath).collect { it.toPath() }), proguardJarOut.name, access, transformers(loader)) } } } tasks.prepareRemapJar { inputFile.set proguardJarOut dependsOn proguardJar } tasks.remapJar { input.set proguardJarOut dependsOn proguardJar } } } } def transformers(loader) { def map = new HashMap(); file(".gradle/proguard-mapping.txt").eachLine { if (!it.startsWith(" ")) { map[it.split(" -> ")[0]] = it.split(" -> ")[1].split(":")[0] } } return [new dev.architectury.transformer.transformers.base.ClassEditTransformer() { @Override dev.architectury.transformer.shadowed.impl.org.objectweb.asm.tree.ClassNode doEdit(String name, dev.architectury.transformer.shadowed.impl.org.objectweb.asm.tree.ClassNode node) { if (dev.architectury.transformer.Transform.trimSlashes(name).startsWith("me/shedaniel/rei/impl")) { if (node.invisibleAnnotations == null || !node.invisibleAnnotations.any { it.desc == "Lorg/jetbrains/annotations/ApiStatus\$Internal;" }) { if (node.invisibleAnnotations == null) node.invisibleAnnotations = new ArrayList<>() node.invisibleAnnotations.add(new dev.architectury.transformer.shadowed.impl.org.objectweb.asm.tree.AnnotationNode("Lorg/jetbrains/annotations/ApiStatus\$Internal;")) } } node.methods.forEach { method -> method.instructions.forEach { insn -> if (insn.opcode == dev.architectury.transformer.shadowed.impl.org.objectweb.asm.Opcodes.LDC && insn instanceof dev.architectury.transformer.shadowed.impl.org.objectweb.asm.tree.LdcInsnNode && insn.cst instanceof String) { if (insn.cst.contains("%s")) { def replaced = insn.cst.replace("%s", loader) if (map.containsKey(replaced)) { insn.cst = map[replaced] } } else { insn.cst = map.getOrDefault(insn.cst, insn.cst) } } } } return node } }, new dev.architectury.transformer.transformers.base.AssetEditTransformer() { @Override void doEdit(dev.architectury.transformer.transformers.base.edit.TransformerContext context, dev.architectury.transformer.input.FileAccess output) throws Exception { def renames = [] output.handle((java.util.function.Consumer) { String name -> def trimmed = dev.architectury.transformer.Transform.trimSlashes(name) if (trimmed.startsWith("META-INF/services/")) { output.modifyFile(trimmed) { bytes -> new String(bytes).split("\n").collect { map[it] ?: it }.join("\n").bytes } def remapped = map[trimmed.substring("META-INF/services/".length())] if (remapped != null) { renames << [trimmed, "META-INF/services/$remapped"] } } }) renames.each { output.addFile(it[1], output.getFile(it[0])) output.deleteFile(it[0]) } output.modifyFile("fabric.mod.json") { bytes -> new String(bytes).split("\n").collect { map.forEach { k, v -> it = it.replace("\"$k\"", "\"$v\"") it = it.replace("\"$k::onInitialize\"", "\"$v::onInitialize\"") it = it.replace("\"$k::onInitializeClient\"", "\"$v::onInitializeClient\"") } it }.join("\n").bytes } } }] }