build.gradle 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. plugins {
  2. id("fabric-loom") version("0.5-SNAPSHOT") apply false
  3. id("maven-publish")
  4. id("java")
  5. id("java-library")
  6. id("net.minecrell.licenser") version("0.4.1")
  7. id("com.matthewprenger.cursegradle") version("1.4.0")
  8. id("net.corda.plugins.jar-filter") version("5.0.8") apply false
  9. }
  10. import net.fabricmc.loom.LoomGradleExtension
  11. import net.fabricmc.loom.task.RemapJarTask
  12. import net.fabricmc.loom.util.DownloadUtil
  13. import net.fabricmc.loom.util.MinecraftVersionInfo
  14. import net.fabricmc.lorenztiny.TinyMappingsReader
  15. import net.fabricmc.mapping.tree.TinyMappingFactory
  16. import org.cadixdev.lorenz.MappingSet
  17. import org.cadixdev.lorenz.io.TextMappingsWriter
  18. import org.cadixdev.lorenz.io.proguard.ProGuardReader
  19. import org.cadixdev.lorenz.model.*
  20. import org.zeroturnaround.zip.ByteSource
  21. import org.zeroturnaround.zip.ZipEntrySource
  22. import org.zeroturnaround.zip.ZipUtil
  23. import java.nio.charset.StandardCharsets
  24. import java.nio.file.Files
  25. import java.nio.file.Path
  26. import java.text.SimpleDateFormat
  27. import java.util.function.Consumer
  28. archivesBaseName = "RoughlyEnoughItems"
  29. version = project.mod_version
  30. group = "me.shedaniel"
  31. allprojects {
  32. apply plugin: 'maven-publish'
  33. apply plugin: 'maven'
  34. apply plugin: 'fabric-loom'
  35. apply plugin: 'net.minecrell.licenser'
  36. apply plugin: 'net.corda.plugins.jar-filter'
  37. sourceCompatibility = targetCompatibility = 1.8
  38. sourceSets {
  39. testmod {
  40. compileClasspath += main.compileClasspath
  41. runtimeClasspath += main.runtimeClasspath
  42. }
  43. }
  44. loom {
  45. shareCaches = true
  46. }
  47. repositories {
  48. maven { url "https://dl.bintray.com/shedaniel/shedaniel-mods" }
  49. mavenLocal()
  50. }
  51. afterEvaluate {
  52. processResources {
  53. filesMatching('fabric.mod.json') {
  54. expand 'version': project.version
  55. }
  56. inputs.property "version", project.version
  57. }
  58. license {
  59. header rootProject.file('HEADER')
  60. include '**/*.java'
  61. }
  62. jar {
  63. from rootProject.file("LICENSE")
  64. }
  65. }
  66. dependencies {
  67. minecraft("com.mojang:minecraft:${project.minecraft_version}")
  68. mappings(new MojangMappingsDependency(project, loom))
  69. modApi("net.fabricmc:fabric-loader:${project.fabricloader_version}")
  70. modApi(fabricApi.module("fabric-api-base", project.fabric_api))
  71. modApi(fabricApi.module("fabric-resource-loader-v0", project.fabric_api))
  72. modApi(fabricApi.module("fabric-networking-v0", project.fabric_api))
  73. modApi(fabricApi.module("fabric-lifecycle-events-v1", project.fabric_api))
  74. modApi(fabricApi.module("fabric-rendering-fluids-v1", project.fabric_api))
  75. modApi("me.shedaniel.cloth.api:cloth-client-events-v0:${cloth_client_events_v0_version}") {
  76. transitive(false)
  77. }
  78. modApi("me.shedaniel.cloth:config-2:${cloth_config_version}") {
  79. exclude(module: "fabric-api")
  80. }
  81. modApi("me.sargunvohra.mcmods:autoconfig1u:${project.autoconfig1u}") {
  82. exclude(module: "fabric-api")
  83. }
  84. modApi("org.jetbrains:annotations:19.0.0")
  85. modCompileOnly("io.github.prospector:modmenu:${modmenu_version}") {
  86. transitive(false)
  87. }
  88. modRuntime("io.github.prospector:modmenu:${modmenu_version}") {
  89. transitive(false)
  90. }
  91. modRuntime("me.shedaniel:SmoothScrollingEverywhere:3.0.3-unstable") {
  92. transitive(false)
  93. }
  94. }
  95. tasks.withType(JavaCompile) {
  96. options.encoding = "UTF-8"
  97. }
  98. task sourcesJar(type: Jar, dependsOn: classes) {
  99. classifier("sources")
  100. from sourceSets.main.allSource
  101. }
  102. }
  103. subprojects {
  104. group = rootProject.group
  105. version = rootProject.version
  106. dependencies {
  107. testmodCompile sourceSets.main.output
  108. }
  109. task remapMavenJar(type: Copy, dependsOn: remapJar) {
  110. afterEvaluate {
  111. from("${project.buildDir}/libs/$archivesBaseName-${version}.jar")
  112. into("${project.buildDir}/libs/")
  113. rename { String fn -> "$archivesBaseName-${version}-maven.jar" }
  114. }
  115. }
  116. configurations {
  117. dev
  118. remapped
  119. }
  120. jar {
  121. classifier("dev")
  122. }
  123. remapJar {
  124. input.set(file("${project.buildDir}/filtered-libs/$archivesBaseName-${version}-dev-filtered.jar"))
  125. classifier(null)
  126. }
  127. artifacts {
  128. dev file: file("${project.buildDir}/libs/$archivesBaseName-${version}-dev.jar"), type: "jar", builtBy: jar
  129. remapped file: file("${project.buildDir}/libs/$archivesBaseName-${version}.jar"), type: "jar", builtBy: remapJar
  130. }
  131. task jarFilter(type: net.corda.gradle.jarfilter.JarFilterTask) {
  132. jars jar
  133. annotations {
  134. forRemove = [
  135. "org.jetbrains.annotations.NotNull",
  136. "org.jetbrains.annotations.Nullable",
  137. "org.jetbrains.annotations.ApiStatus\$Experimental",
  138. "org.jetbrains.annotations.ApiStatus\$Internal",
  139. "org.jetbrains.annotations.ApiStatus\$ScheduledForRemoval",
  140. "org.jetbrains.annotations.ApiStatus\$AvailableSince",
  141. "org.jetbrains.annotations.ApiStatus\$NonExtendable",
  142. "org.jetbrains.annotations.ApiStatus\$OverrideOnly"
  143. ]
  144. }
  145. }
  146. remapJar.dependsOn("jarFilter")
  147. publishing {
  148. publications {
  149. create("${archivesBaseName}_mavenJava", MavenPublication) {
  150. afterEvaluate {
  151. artifact(file("${project.buildDir}/libs/$archivesBaseName-${version}-maven.jar")) {
  152. builtBy remapMavenJar
  153. }
  154. artifact(sourcesJar) {
  155. builtBy remapSourcesJar
  156. }
  157. }
  158. }
  159. }
  160. repositories {
  161. if (project.hasProperty('danielshe_pass')) {
  162. maven {
  163. url = "http://deploy.modmuss50.me/"
  164. credentials {
  165. username = "danielshe"
  166. password = project.getProperty('danielshe_pass')
  167. }
  168. }
  169. }
  170. }
  171. }
  172. }
  173. task licenseFormatAll
  174. subprojects { licenseFormatAll.dependsOn("${path}:licenseFormat") }
  175. subprojects { rootProject.remapJar.dependsOn("${path}:remapJar") }
  176. task remapMavenJar(type: RemapJarTask, dependsOn: jar) {
  177. afterEvaluate {
  178. input.set(file("${project.buildDir}/libs/${archivesBaseName}-${version}-dev.jar"))
  179. archiveName = "${archivesBaseName}-${version}-maven.jar"
  180. addNestedDependencies.set(false)
  181. }
  182. }
  183. sourceSets {
  184. testmod
  185. }
  186. dependencies {
  187. afterEvaluate {
  188. subprojects.each {
  189. compile project(path: ":${it.name}", configuration: "dev")
  190. include project(path: ":${it.name}", configuration: "remapped")
  191. testmodCompile project("${it.name}:").sourceSets.testmod.output
  192. }
  193. def listAdded = new ArrayList(Arrays.asList((api_exculde as String).split(',')))
  194. def eachDep = { dep ->
  195. for (apiIncludeDepStr in (api_include as String).split(',')) {
  196. if (apiIncludeDepStr.isEmpty()) continue
  197. def apiIncludeGroup = apiIncludeDepStr.split(':')[0]
  198. def apiIncludeDep = apiIncludeDepStr.split(':')[1]
  199. if (dep.module.id.group == apiIncludeGroup && dep.module.id.name.startsWith(apiIncludeDep)) {
  200. def version = dep.module.id.version.indexOf('@') >= 0 ? dep.module.id.version.substring(0, dep.module.id.version.indexOf('@')) : dep.module.id.version
  201. def mavenDep = "${dep.module.id.group}:${dep.module.id.name}:$version"
  202. if (!(mavenDep in listAdded)) {
  203. include(mavenDep) {
  204. transitive = false
  205. }
  206. listAdded.add(mavenDep)
  207. }
  208. break
  209. }
  210. }
  211. }
  212. rootProject.configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.each eachDep
  213. rootProject.configurations.runtimeClasspath.resolvedConfiguration.firstLevelModuleDependencies.each eachDep
  214. }
  215. }
  216. def releaseChangelog = "No changelog"
  217. /* Thank you modmenu & fablabs */
  218. task releaseOnCf {
  219. def df = new SimpleDateFormat("yyyy-MM-dd HH:mm")
  220. df.setTimeZone(TimeZone.getTimeZone("UTC"))
  221. def branch
  222. if (System.env.BRANCH_NAME) {
  223. branch = System.env.BRANCH_NAME
  224. branch = branch.substring(branch.lastIndexOf("/") + 1)
  225. } else {
  226. branch = "git rev-parse --abbrev-ref HEAD".execute().in.text.trim()
  227. }
  228. if (branch == "HEAD") {
  229. branch = "git rev-parse --short HEAD".execute().in.text.trim()
  230. }
  231. def time = df.format(new Date())
  232. def changes = new StringBuilder()
  233. changes << "<h2>REI v$project.version for $project.supported_version</h2>Updated at <b>$time</b>.<br><a href=\"https://www.github.com/shedaniel/RoughlyEnoughItems/commits/$branch\">Click here for changelog</a>"
  234. def proc = "git log --max-count=200 --pretty=format:%s".execute()
  235. proc.in.eachLine { line ->
  236. def processedLine = line.toString()
  237. if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {
  238. changes << "<br>- ${processedLine.capitalize()}"
  239. }
  240. }
  241. proc.waitFor()
  242. releaseChangelog = changes.toString()
  243. dependsOn tasks.getByName("curseforge")
  244. }
  245. curseforge {
  246. if (project.hasProperty('danielshe_curse_api_key') || System.getenv('danielshe_curse_api_key') != null) {
  247. apiKey = project.hasProperty('danielshe_curse_api_key') ? project.property('danielshe_curse_api_key') : System.getenv('danielshe_curse_api_key')
  248. project {
  249. id = "310111"
  250. releaseType = "release"
  251. changelogType = "html"
  252. changelog = releaseChangelog
  253. addGameVersion "1.16-Snapshot"
  254. addGameVersion "1.16.2"
  255. addGameVersion "1.16.3"
  256. addGameVersion "1.16.4"
  257. addGameVersion "Java 8"
  258. addGameVersion "Fabric"
  259. relations {
  260. requiredDependency "fabric-api"
  261. embeddedLibrary "cloth-api"
  262. embeddedLibrary "cloth-config"
  263. embeddedLibrary "auto-config-updated-api"
  264. }
  265. mainArtifact(file("${project.buildDir}/libs/${project.archivesBaseName}-${project.version}.jar")) {
  266. displayName = "[Fabric $project.supported_version] v$project.version"
  267. }
  268. addArtifact(file("${project.buildDir}/libs/${project.archivesBaseName}-${project.version}-sources.jar")) {
  269. displayName = "[Fabric $project.supported_version] v$project.version Sources"
  270. }
  271. afterEvaluate {
  272. uploadTask.dependsOn("build")
  273. }
  274. }
  275. }
  276. options {
  277. forgeGradleIntegration = false
  278. javaVersionAutoDetect = false
  279. }
  280. }
  281. publishing {
  282. publications {
  283. mavenJava(MavenPublication) {
  284. artifact(file("${project.buildDir}/libs/$archivesBaseName-${version}-maven.jar")) {
  285. builtBy remapMavenJar
  286. }
  287. artifact(sourcesJar) {
  288. builtBy remapSourcesJar
  289. }
  290. pom.withXml {
  291. def depsNode = asNode().appendNode("dependencies")
  292. subprojects.each {
  293. def depNode = depsNode.appendNode("dependency")
  294. depNode.appendNode("groupId", it.group)
  295. depNode.appendNode("artifactId", it.name)
  296. depNode.appendNode("version", it.version)
  297. depNode.appendNode("scope", "compile")
  298. }
  299. }
  300. }
  301. }
  302. repositories {
  303. if (project.hasProperty('danielshe_pass')) {
  304. maven {
  305. url = "http://deploy.modmuss50.me/"
  306. credentials {
  307. username = "danielshe"
  308. password = project.getProperty('danielshe_pass')
  309. }
  310. }
  311. }
  312. }
  313. }
  314. /*
  315. The following code is licensed under MIT License.
  316. Copyright (c) 2016 FabricMC
  317. Permission is hereby granted, free of charge, to any person obtaining a copy
  318. of this software and associated documentation files (the "Software"), to deal
  319. in the Software without restriction, including without limitation the rights
  320. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  321. copies of the Software, and to permit persons to whom the Software is
  322. furnished to do so, subject to the following conditions:
  323. The above copyright notice and this permission notice shall be included in all
  324. copies or substantial portions of the Software.
  325. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  326. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  327. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  328. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  329. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  330. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  331. SOFTWARE.
  332. */
  333. class MojangMappingsDependency implements SelfResolvingDependency {
  334. private final Project project
  335. private final LoomGradleExtension extension
  336. MojangMappingsDependency(Project project, LoomGradleExtension extension) {
  337. this.project = project
  338. this.extension = extension
  339. }
  340. @Override
  341. Set<File> resolve() {
  342. Path mappingsDir = extension.getMappingsProvider().getMappingsDir()
  343. Path mappingsFile = mappingsDir.resolve(String.format("net.mojang.minecraft-mappings-%s.tiny", getVersion()))
  344. Path clientMappings = mappingsDir.resolve(String.format("net.mojang.minecraft.mappings-%s-client.map", getVersion()))
  345. Path serverMappings = mappingsDir.resolve(String.format("net.mojang.minecraft.mappings-%s-server.map", getVersion()))
  346. if (!Files.exists(mappingsFile) || project.getGradle().getStartParameter().isRefreshDependencies()) {
  347. MappingSet mappingSet
  348. try {
  349. mappingSet = getMappingsSet(clientMappings, serverMappings)
  350. Writer writer = new StringWriter()
  351. new TinyWriter(writer, "intermediary", "named").write(mappingSet)
  352. Files.deleteIfExists(mappingsFile)
  353. ZipUtil.pack([
  354. new ByteSource("mappings/mappings.tiny", writer.toString().getBytes(StandardCharsets.UTF_8))
  355. ] as ZipEntrySource[], mappingsFile.toFile())
  356. writer.close()
  357. } catch (IOException e) {
  358. throw new RuntimeException("Failed to resolve Mojang mappings", e)
  359. }
  360. }
  361. return Collections.singleton(mappingsFile.toFile())
  362. }
  363. private MappingSet getMappingsSet(Path clientMappings, Path serverMappings) throws IOException {
  364. MinecraftVersionInfo versionInfo = extension.getMinecraftProvider().getVersionInfo()
  365. if (versionInfo.downloads.get("client_mappings") == null) {
  366. throw new RuntimeException("Failed to find official mojang mappings for " + getVersion())
  367. }
  368. String clientMappingsUrl = versionInfo.downloads.get("client_mappings").url
  369. String serverMappingsUrl = versionInfo.downloads.get("server_mappings").url
  370. DownloadUtil.downloadIfChanged(new URL(clientMappingsUrl), clientMappings.toFile(), project.getLogger())
  371. DownloadUtil.downloadIfChanged(new URL(serverMappingsUrl), serverMappings.toFile(), project.getLogger())
  372. MappingSet mappings = MappingSet.create()
  373. BufferedReader clientBufferedReader = Files.newBufferedReader(clientMappings, StandardCharsets.UTF_8)
  374. BufferedReader serverBufferedReader = Files.newBufferedReader(serverMappings, StandardCharsets.UTF_8)
  375. ProGuardReader proGuardReaderClient = new ProGuardReader(clientBufferedReader)
  376. ProGuardReader proGuardReaderServer = new ProGuardReader(serverBufferedReader)
  377. proGuardReaderClient.read(mappings)
  378. proGuardReaderServer.read(mappings)
  379. clientBufferedReader.close()
  380. serverBufferedReader.close()
  381. proGuardReaderClient.close()
  382. proGuardReaderServer.close()
  383. MappingSet officialToNamed = mappings.reverse()
  384. MappingSet intermediaryToOfficial
  385. BufferedReader reader = Files.newBufferedReader(extension.getMappingsProvider().getIntermediaryTiny(), StandardCharsets.UTF_8)
  386. intermediaryToOfficial = new TinyMappingsReader(TinyMappingFactory.loadWithDetection(reader), "intermediary", "official").read()
  387. reader.close()
  388. MappingSet intermediaryToMojang = MappingSet.create()
  389. // Merging. Don't use MappingSet#merge
  390. iterateClasses(intermediaryToOfficial, { inputMappings ->
  391. officialToNamed.getClassMapping(inputMappings.getFullDeobfuscatedName())
  392. .ifPresent({ namedClass ->
  393. ClassMapping mojangClassMapping = intermediaryToMojang.getOrCreateClassMapping(inputMappings.getFullObfuscatedName())
  394. .setDeobfuscatedName(namedClass.getFullDeobfuscatedName())
  395. for (FieldMapping fieldMapping : inputMappings.getFieldMappings()) {
  396. namedClass.getFieldMapping(fieldMapping.getDeobfuscatedName())
  397. .ifPresent({ namedField ->
  398. mojangClassMapping.getOrCreateFieldMapping(fieldMapping.getSignature())
  399. .setDeobfuscatedName(namedField.getDeobfuscatedName())
  400. })
  401. }
  402. for (MethodMapping methodMapping : inputMappings.getMethodMappings()) {
  403. namedClass.getMethodMapping(methodMapping.getDeobfuscatedSignature())
  404. .ifPresent({ namedMethod ->
  405. mojangClassMapping.getOrCreateMethodMapping(methodMapping.getSignature())
  406. .setDeobfuscatedName(namedMethod.getDeobfuscatedName())
  407. })
  408. }
  409. })
  410. })
  411. return intermediaryToMojang
  412. }
  413. @Override
  414. Set<File> resolve(boolean transitive) {
  415. return resolve()
  416. }
  417. @Override
  418. TaskDependency getBuildDependencies() {
  419. return { Collections.emptySet() }
  420. }
  421. @Override
  422. String getGroup() {
  423. return "net.mojang.minecraft"
  424. }
  425. @Override
  426. String getName() {
  427. return "mappings"
  428. }
  429. @Override
  430. String getVersion() {
  431. return extension.getMinecraftProvider().getMinecraftVersion()
  432. }
  433. @Override
  434. boolean contentEquals(Dependency dependency) {
  435. if (dependency instanceof MojangMappingsDependency) {
  436. return ((MojangMappingsDependency) dependency).extension.getMinecraftProvider().getMinecraftVersion() == getVersion()
  437. }
  438. return false
  439. }
  440. @Override
  441. Dependency copy() {
  442. return new MojangMappingsDependency(project, extension)
  443. }
  444. @Override
  445. String getReason() {
  446. return null
  447. }
  448. @Override
  449. void because(String s) {
  450. }
  451. private static void iterateClasses(MappingSet mappings, Closure<ClassMapping> consumer) {
  452. for (TopLevelClassMapping classMapping : mappings.getTopLevelClassMappings()) {
  453. iterateClass(classMapping, consumer)
  454. }
  455. }
  456. private static void iterateClass(ClassMapping classMapping, Consumer<ClassMapping> consumer) {
  457. consumer.accept(classMapping)
  458. for (InnerClassMapping innerClassMapping : classMapping.getInnerClassMappings()) {
  459. iterateClass(innerClassMapping, consumer)
  460. }
  461. }
  462. private static class TinyWriter extends TextMappingsWriter {
  463. private final String namespaceFrom
  464. private final String namespaceTo
  465. protected TinyWriter(Writer writer, String namespaceFrom, String namespaceTo) {
  466. super(writer)
  467. this.namespaceFrom = namespaceFrom
  468. this.namespaceTo = namespaceTo
  469. }
  470. @Override
  471. void write(MappingSet mappings) {
  472. writer.println("tiny\t2\t0\t" + namespaceFrom + "\t" + namespaceTo)
  473. iterateClasses(mappings, { classMapping ->
  474. writer.println("c\t" + classMapping.getFullObfuscatedName() + "\t" + classMapping.getFullDeobfuscatedName())
  475. for (FieldMapping fieldMapping : classMapping.getFieldMappings()) {
  476. fieldMapping.getType().ifPresent({ fieldType ->
  477. writer.println("\tf\t" + fieldType + "\t" + fieldMapping.getObfuscatedName() + "\t" + fieldMapping.getDeobfuscatedName())
  478. })
  479. }
  480. for (MethodMapping methodMapping : classMapping.getMethodMappings()) {
  481. writer.println("\tm\t" + methodMapping.getSignature().getDescriptor() + "\t" + methodMapping.getObfuscatedName() + "\t" + methodMapping.getDeobfuscatedName())
  482. }
  483. })
  484. }
  485. }
  486. }