From d4ec97f4f2fa33d4b71b525888821cc6887475be Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 11:17:55 +0700 Subject: [PATCH 01/92] refactor: Handle Minecraft's new version format --- build.gradle.kts | 14 +++----- buildSrc/src/main/kotlin/VersionRange.kt | 3 +- .../src/main/kotlin/dependencies/Create.kt | 2 +- .../main/kotlin/dependencies/Dependencies.kt | 36 +++++++++++++------ .../src/main/kotlin/dependencies/FabricAPI.kt | 6 ++-- .../src/main/kotlin/dependencies/LexForge.kt | 2 +- .../src/main/kotlin/dependencies/Minecraft.kt | 4 +-- .../src/main/kotlin/dependencies/NeoForge.kt | 7 ++-- .../main/kotlin/dependencies/RecipeViewer.kt | 10 +++--- cobblegen/build.gradle.kts | 29 ++++++++------- 10 files changed, 62 insertions(+), 51 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d42408e6..b59e8506 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,13 +19,11 @@ val loaderName = project.properties["null2264.platform"] as? String ?: "" val isForge = loaderName.endsWith("forge") val isNeo = loaderName.endsWith("neoforge") val isFabric = loaderName.endsWith("fabric") -val _mcVer = project.properties["mcVer"] as? String ?: "" -val mcVersionStr = if (_mcVer.startsWith("1.")) _mcVer else "2.$_mcVer" -val (major, minor, patch, hotfix) = mcVersionStr +val mcVersionStr = project.properties["mcVer"] as? String ?: "" +val (major, minor, patch) = mcVersionStr .split(".") .toMutableList() - .apply { while (this.size < 4) this.add("") } -val mcHotfix: Int = hotfix.toIntOrNull() ?: 0 + .apply { while (this.size < 3) this.add("") } val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() val versionRange = supportedVersionRange(mcVersion, loaderName) @@ -33,7 +31,6 @@ fun setupPreprocessor() { val buildProps = buildString { append("# DON'T TOUCH THIS FILE, This is handled by the build script\n") append("MC=${mcVersion}\n") - append("BUILD=${mcHotfix}\n") if (isFabric) append("FABRIC=1\n") if (isForge) append("FORGE=${if (!isNeo) "1" else "2"}\n") } @@ -43,7 +40,7 @@ fun setupPreprocessor() { setupPreprocessor() architectury { - minecraft = MC.versioned(mcVersion, mcHotfix) + minecraft = MC.versioned(mcVersion) } allprojects { @@ -52,7 +49,6 @@ allprojects { ext["mcVersion"] = mcVersion ext["mcVersionStr"] = mcVersionStr - ext["mcHotfix"] = mcHotfix ext["loaderName"] = loaderName ext["isFabric"] = isFabric ext["isForge"] = isForge @@ -194,7 +190,7 @@ subprojects { val minecraft by configurations val mappings by configurations - minecraft(MC.versioned(mcVersion, mcHotfix)) + minecraft(MC.versioned(mcVersion)) mappings(loom.officialMojangMappings()) } diff --git a/buildSrc/src/main/kotlin/VersionRange.kt b/buildSrc/src/main/kotlin/VersionRange.kt index 9a08ac7c..7a54f419 100644 --- a/buildSrc/src/main/kotlin/VersionRange.kt +++ b/buildSrc/src/main/kotlin/VersionRange.kt @@ -71,7 +71,8 @@ fun supportedVersionRange(mcVersion: Int, loader: String): VersionRange { in 12100..12101 -> VersionRange("1.20.x", "1.21.1") in 12102..12104 -> VersionRange("1.21.1", "1.21.4") in 12105..12110 -> VersionRange("1.21.4", "1.21.10") - 12111 -> VersionRange("1.21.10", null) + 12111 -> VersionRange("1.21.10", "1.21.11") + 22601 -> VersionRange("1.21.11", null) else -> VersionRange(null, null) } } diff --git a/buildSrc/src/main/kotlin/dependencies/Create.kt b/buildSrc/src/main/kotlin/dependencies/Create.kt index 4c7ec30e..8401b13e 100644 --- a/buildSrc/src/main/kotlin/dependencies/Create.kt +++ b/buildSrc/src/main/kotlin/dependencies/Create.kt @@ -4,7 +4,7 @@ fun createMod(isNeo: Boolean) = Dependency( group = "com.simibubi.create", // Create finally support Neo on 1.21.1 name = "create" + (if (!isNeo) "-1.18.2" else "-1.21.1"), - version = { mcVersion, hotfix -> + version = { mcVersion -> val version = if (!isNeo) "0.5.1.e-318" else "6.0.4-59" return@Dependency "$version:slim" }, diff --git a/buildSrc/src/main/kotlin/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/dependencies/Dependencies.kt index f78e1291..7acba737 100644 --- a/buildSrc/src/main/kotlin/dependencies/Dependencies.kt +++ b/buildSrc/src/main/kotlin/dependencies/Dependencies.kt @@ -3,26 +3,42 @@ package dependencies data class Dependency( private val group: String, private val name: String, - private val version: (Int, Int) -> String, + private val version: (Int) -> String, ) { - fun versioned(mcVersion: Int, mcBuild: Int): String = "${group}:${name}:${version(mcVersion, mcBuild)}" + fun versioned(mcVersion: Int): String = "${group}:${name}:${version(mcVersion)}" } -fun versionStr(versionCode: Int, hotfix: Int = 0, alwaysShowHotfix: Boolean = false): String { +fun legacyVersionStr(versionCode: Int): String { val versionCodeStr = versionCode.toString() val major = versionCodeStr.getOrNull(0)?.toString() ?: "0" val minor = versionCodeStr - .substring(1, 3 + (versionCodeStr.length - 5)) // Future proofing, in case "1.100.0" happened + .substring(1, 3) .padStart(2, '0') .trimStart('0') val patch = versionCodeStr - .substring(3 + (versionCodeStr.length - 5)) + .substring(3) .padEnd(1, '0').trimStart('0') + + if (patch.isEmpty()) return "$major.$minor" + return "$major.$minor.$patch" +} + +/** + * Transform version code (e.g. 260100) back to formatted string (e.g. 26.01). + */ +fun versionStr(versionCode: Int, alwaysShowHotfix: Boolean = false): String { + val versionCodeStr = versionCode.toString() + if (versionCodeStr.length == 5) return legacyVersionStr(versionCode) - if (major.toInt() <= 1) { - if (patch.isEmpty()) return "$major.$minor" - return "$major.$minor.$patch" - } + val year = versionCodeStr.substring(0, 2) + val release = versionCodeStr + .substring(2, 4) + .trimStart('0') + .let { if (it == "") "0" else it } + val hotfix = versionCodeStr + .substring(4) + .trimStart('0') + .let { if (it == "" && alwaysShowHotfix) "0" else it } - return if (hotfix > 0 || alwaysShowHotfix) "$minor.$patch.$hotfix" else "$minor.$patch" + return if (hotfix != "") "$year.$release.$hotfix" else "$year.$release" } diff --git a/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt b/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt index 1032f2f4..8abb0e9b 100644 --- a/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt +++ b/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt @@ -3,7 +3,7 @@ package dependencies val fapi = Dependency( group = "net.fabricmc.fabric-api", name = "fabric-api", - version = { mcVersion, hotfix -> + version = { mcVersion -> when (mcVersion) { 11605 -> "0.42.0+1.16" 11802 -> "0.76.0+1.18.2" @@ -24,7 +24,7 @@ val fapi = Dependency( val fapiGameTest = Dependency( group = "net.fabricmc.fabric-api", name = "fabric-gametest-api-v1", - version = { mcVersion, hotfix -> + version = { mcVersion -> when (mcVersion) { 12105 -> "3.1.2+2a6ec84b49" else -> throw IllegalStateException("$mcVersion is not yet supported!") @@ -35,7 +35,7 @@ val fapiGameTest = Dependency( val fapiResourceLoader = Dependency( group = "net.fabricmc.fabric-api", name = "fabric-resource-loader-v0", - version = { mcVersion, hotfix -> + version = { mcVersion -> when (mcVersion) { 12105 -> "3.1.6+02ca679649" else -> throw IllegalStateException("$mcVersion is not yet supported!") diff --git a/buildSrc/src/main/kotlin/dependencies/LexForge.kt b/buildSrc/src/main/kotlin/dependencies/LexForge.kt index 54969660..dac39b98 100644 --- a/buildSrc/src/main/kotlin/dependencies/LexForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/LexForge.kt @@ -3,7 +3,7 @@ package dependencies val lexForge = Dependency( group = "net.minecraftforge", name = "forge", - version = { mcVersion, hotfix -> + version = { mcVersion -> val version = when (mcVersion) { 11605 -> "36.2.41" 11802 -> "40.2.9" diff --git a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt index c0fc00b8..ac292d36 100644 --- a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt +++ b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt @@ -3,11 +3,11 @@ package dependencies val minecraft = Dependency( group = "com.mojang", name = "minecraft", - version = { mcVersion, hotfix -> + version = { mcVersion -> when (mcVersion) { // For snapshots //12100 -> "some snapshot" - else -> versionStr(mcVersion, hotfix) + else -> versionStr(mcVersion) } }, ) diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index 8a173e7a..ec9398a7 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -14,13 +14,10 @@ val neoForge = Dependency( in 12102..12104 -> "1-beta" in 12105..12110 -> "25-beta" 12111 -> "24-beta" - 22601 -> when (hotfix) { - 0 -> "0-alpha.4+snapshot-1" - else -> throw IllegalStateException("Hotfix $hotfix is not yet supported!") - } + 260100 -> "0-alpha.4+snapshot-1" else -> throw IllegalStateException("Version $mcVersion is not yet supported!") } - val mc = versionStr(mcVersion, hotfix, true).substring(2) + val mc = versionStr(mcVersion, true) "${mc}.${version}" }, diff --git a/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt b/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt index b1d84496..d0d1f75c 100644 --- a/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt +++ b/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt @@ -6,7 +6,7 @@ fun emi(mcVersion: Int, loader: String? = null, api: Boolean = false) = Dependen // EMI migrate to NeoForge after 1.20.2 if (loader != "fabric" && mcVersion <= 12002) "emi-forge" else "emi-$loader" } else "emi", - version = { _, _ -> + version = { _ -> buildString { if (mcVersion <= 11802) { append("0.7.3+${versionStr(mcVersion)}") // There are no multi-loader support in 1.18.2 @@ -22,6 +22,7 @@ fun emi(mcVersion: Int, loader: String? = null, api: Boolean = false) = Dependen 12003 -> "1.20.2" in 12005..12006 -> "1.20.6" in 12100..12111 -> "1.21.1" + 260100 -> "1.21.1" // FIXME: Not confirmed, but EMI might skip 1.21.11 for 26.1 else -> throw IllegalStateException("$mcVersion is not yet supported!") } ) @@ -38,7 +39,7 @@ fun rei(loader: String, api: Boolean = false) = Dependency( } else { "RoughlyEnoughItems-$loader" }, - version = { mcVersion, hotfix -> + version = { mcVersion -> // They didn't break API on MC version upgrade so mismatch should be fine when (mcVersion) { 11802 -> "8.3.618" @@ -48,7 +49,8 @@ fun rei(loader: String, api: Boolean = false) = Dependency( in 12002..12004 -> "13.0.685" in 12005..12006 -> "15.0.787" in 12100..12101 -> "16.0.788" - in 12102..12111 -> "17.0.789" + in 12102..12110 -> "17.0.789" + 12111 -> "17.0.789" // FIXME: Broken in 1.21.11, waiting for new release else -> throw IllegalStateException("$mcVersion is not yet supported!") } }, @@ -83,7 +85,7 @@ fun jei(mcVersion: Int, loader: String, common: Boolean = false, api: Boolean = append ("-api") } }, - version = { _, _ -> + version = { _ -> // They didn't break API on MC version upgrade so mismatch should be fine when (mcVersion) { 11802 -> "10.2.1.1009" diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 8aa5d771..59d7a5fe 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -7,7 +7,6 @@ plugins { val mcVersion = ext["mcVersion"] as Int val mcVersionStr = ext["mcVersionStr"] as String -val mcHotfix = ext["mcHotfix"] as Int val loaderName = ext["loaderName"] as String val isFabric = ext["isFabric"] as Boolean val isForge = ext["isForge"] as Boolean @@ -84,17 +83,17 @@ dependencies { // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env // REF: https://github.com/FabricMC/fabric/issues/4491 if (mcVersion in 11606..12104) { - modLocalRuntime(fapi.versioned(mcVersion, mcHotfix)) + modLocalRuntime(fapi.versioned(mcVersion)) } else if (mcVersion in 12105..12110) { // FIXME: Is Resource Loader even needed? - //modLocalRuntime(fapiResourceLoader.versioned(mcVersion, mcHotfix)) - modLocalRuntime(fapiGameTest.versioned(mcVersion, mcHotfix)) + //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) + modLocalRuntime(fapiGameTest.versioned(mcVersion)) } } else { if (!isNeo) { - "forge"(lexForge.versioned(mcVersion, mcHotfix)) + "forge"(lexForge.versioned(mcVersion)) } else { - "neoForge"(neoForge.versioned(mcVersion, mcHotfix)) + "neoForge"(neoForge.versioned(mcVersion)) } } @@ -110,19 +109,19 @@ dependencies { // <- EMI if (mcVersion <= 11802) { - modCompileOnly(emi(mcVersion, null, api = true).versioned(0, 0)) + modCompileOnly(emi(mcVersion, null, api = true).versioned(0)) if (project.properties["recipe_viewer"] == "emi" && isFabric) - modLocalRuntime(emi(mcVersion).versioned(0, 0)) + modLocalRuntime(emi(mcVersion).versioned(0)) } else { - modCompileOnly(emi(mcVersion, loaderName, api = true).versioned(0, 0)) + modCompileOnly(emi(mcVersion, loaderName, api = true).versioned(0)) if (project.properties["recipe_viewer"] == "emi") - modLocalRuntime(emi(mcVersion, loaderName).versioned(0, 0)) + modLocalRuntime(emi(mcVersion, loaderName).versioned(0)) } // EMI -> // <- REI // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* - modCompileOnly(rei(loaderName, true).versioned(mcVersion, mcHotfix)) + modCompileOnly(rei(loaderName, true).versioned(mcVersion)) if (mcVersion in 12002..12104) { // FIXME: Not sure why it's not included modCompileOnly("me.shedaniel.cloth:basic-math:0.6.1") modCompileOnly("dev.architectury:architectury:11.1.13") @@ -130,15 +129,15 @@ dependencies { if (project.properties["recipe_viewer"] == "rei") { if (mcVersion == 11902) // REI's stupid dep bug modLocalRuntime("dev.architectury:architectury-fabric:6.5.77") - modLocalRuntime(rei(loaderName).versioned(mcVersion, mcHotfix)) + modLocalRuntime(rei(loaderName).versioned(mcVersion)) } // REI -> // <- JEI - modCompileOnly(jei(mcVersion, loaderName, common = true, api = true).versioned(0, 0)) - modCompileOnly(jei(mcVersion, loaderName, common = false, api = true).versioned(0, 0)) + modCompileOnly(jei(mcVersion, loaderName, common = true, api = true).versioned(0)) + modCompileOnly(jei(mcVersion, loaderName, common = false, api = true).versioned(0)) if (project.properties["recipe_viewer"] == "jei") - modCompileOnly(jei(mcVersion, loaderName, common = false, api = false).versioned(0, 0)) + modCompileOnly(jei(mcVersion, loaderName, common = false, api = false).versioned(0)) // JEI -> /* FIXME: Broken, somehow From 4858e86e72952f39428e1f7b6688aa0ba05ff3f0 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 12:43:25 +0700 Subject: [PATCH 02/92] fix: Fix build --- buildSrc/src/main/kotlin/dependencies/FabricAPI.kt | 5 ++++- buildSrc/src/main/kotlin/dependencies/Minecraft.kt | 1 + buildSrc/src/main/kotlin/dependencies/NeoForge.kt | 2 +- buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt | 3 +++ cobblegen/build.gradle.kts | 11 +++++++---- versions.json | 3 +++ 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt b/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt index 8abb0e9b..07fb5c42 100644 --- a/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt +++ b/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt @@ -16,6 +16,7 @@ val fapi = Dependency( in 12102..12104 -> "0.106.1+1.21.3" in 12105..12110 -> "0.119.9+1.21.5" 12111 -> "0.139.5+1.21.11" + 260100 -> "0.141.1+26.1" else -> throw IllegalStateException("$mcVersion is not yet supported!") } }, @@ -26,7 +27,9 @@ val fapiGameTest = Dependency( name = "fabric-gametest-api-v1", version = { mcVersion -> when (mcVersion) { - 12105 -> "3.1.2+2a6ec84b49" + in 12105..12110 -> "3.1.2+2a6ec84b49" + 12111 -> "3.1.27+4fc5413f3e" + 260100 -> "4.0.0+574290bac9" else -> throw IllegalStateException("$mcVersion is not yet supported!") } }, diff --git a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt index ac292d36..a8726c6a 100644 --- a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt +++ b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt @@ -7,6 +7,7 @@ val minecraft = Dependency( when (mcVersion) { // For snapshots //12100 -> "some snapshot" + 260100 -> "26.1-snapshot-1" else -> versionStr(mcVersion) } }, diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index ec9398a7..75037e07 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -3,7 +3,7 @@ package dependencies val neoForge = Dependency( group = "net.neoforged", name = "neoforge", - version = { mcVersion, hotfix -> + version = { mcVersion -> val version = when (mcVersion) { // snapshot version format: // "0-alpha.${mc[mcVersion]}.+" diff --git a/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt b/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt index d0d1f75c..7a4636c9 100644 --- a/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt +++ b/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt @@ -51,6 +51,7 @@ fun rei(loader: String, api: Boolean = false) = Dependency( in 12100..12101 -> "16.0.788" in 12102..12110 -> "17.0.789" 12111 -> "17.0.789" // FIXME: Broken in 1.21.11, waiting for new release + 260100 -> "17.0.789" else -> throw IllegalStateException("$mcVersion is not yet supported!") } }, @@ -71,6 +72,7 @@ fun jei(mcVersion: Int, loader: String, common: Boolean = false, api: Boolean = in 12005..12006 -> versionStr(mcVersion) in 12100..12110 -> "1.21.1" 12111 -> "1.21.11" + 260100 -> "1.21.11" else -> throw IllegalStateException("$mcVersion is not yet supported!") } ) @@ -96,6 +98,7 @@ fun jei(mcVersion: Int, loader: String, common: Boolean = false, api: Boolean = in 12005..12006 -> "18.0.0.62" in 12100..12110 -> "19.21.1.248" 12111 -> "27.3.0.14" + 260100 -> "27.3.0.14" else -> throw IllegalStateException("$mcVersion is not yet supported!") } }, diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 59d7a5fe..6a86bfb5 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -84,10 +84,13 @@ dependencies { // REF: https://github.com/FabricMC/fabric/issues/4491 if (mcVersion in 11606..12104) { modLocalRuntime(fapi.versioned(mcVersion)) - } else if (mcVersion in 12105..12110) { - // FIXME: Is Resource Loader even needed? - //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) - modLocalRuntime(fapiGameTest.versioned(mcVersion)) + } else { + try { + // FIXME: Is Resource Loader even needed? + //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) + modLocalRuntime(fapiGameTest.versioned(mcVersion)) + } catch (e: IllegalStateException) { + } } } else { if (!isNeo) { diff --git a/versions.json b/versions.json index 19316cd2..5157efe5 100644 --- a/versions.json +++ b/versions.json @@ -33,5 +33,8 @@ { "mc": "1.21.11", "loader": "fabric", "java": "21", "testVersions": ["1.21.11"] }, { "mc": "1.21.11", "loader": "neoforge", "java": "21", "testVersions": ["1.21.11"] } + + { "mc": "26.1", "loader": "fabric", "java": "21", "testVersions": [] }, + { "mc": "26.1", "loader": "neoforge", "java": "21", "testVersions": [] } ] } From 1a0c300774c7ec85cf92e2779f59496150c66c83 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 12:44:32 +0700 Subject: [PATCH 03/92] fix: GitHub Action can't cope with empty array --- versions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/versions.json b/versions.json index 5157efe5..c964c513 100644 --- a/versions.json +++ b/versions.json @@ -34,7 +34,7 @@ { "mc": "1.21.11", "loader": "fabric", "java": "21", "testVersions": ["1.21.11"] }, { "mc": "1.21.11", "loader": "neoforge", "java": "21", "testVersions": ["1.21.11"] } - { "mc": "26.1", "loader": "fabric", "java": "21", "testVersions": [] }, - { "mc": "26.1", "loader": "neoforge", "java": "21", "testVersions": [] } + { "mc": "26.1", "loader": "fabric", "java": "21", "testVersions": ["26.1"] }, + { "mc": "26.1", "loader": "neoforge", "java": "21", "testVersions": ["26.1"] } ] } From 2b752e8f5ad52f872839c4e3e4c173b63ba84525 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 15:18:03 +0700 Subject: [PATCH 04/92] fix: Malformed json --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index c964c513..5d11bec8 100644 --- a/versions.json +++ b/versions.json @@ -32,7 +32,7 @@ { "mc": "1.21.5", "loader": "neoforge", "java": "21", "testVersions": ["1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10"] }, { "mc": "1.21.11", "loader": "fabric", "java": "21", "testVersions": ["1.21.11"] }, - { "mc": "1.21.11", "loader": "neoforge", "java": "21", "testVersions": ["1.21.11"] } + { "mc": "1.21.11", "loader": "neoforge", "java": "21", "testVersions": ["1.21.11"] }, { "mc": "26.1", "loader": "fabric", "java": "21", "testVersions": ["26.1"] }, { "mc": "26.1", "loader": "neoforge", "java": "21", "testVersions": ["26.1"] } From 122f3208c55c0d53bf10db8b5e1bdf100da0cafe Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 15:53:04 +0700 Subject: [PATCH 05/92] fix: Fix neo build --- buildSrc/src/main/kotlin/dependencies/NeoForge.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index 75037e07..7f88aa1d 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -17,7 +17,7 @@ val neoForge = Dependency( 260100 -> "0-alpha.4+snapshot-1" else -> throw IllegalStateException("Version $mcVersion is not yet supported!") } - val mc = versionStr(mcVersion, true) + val mc = versionStr(mcVersion, true).let { if (mcVersion>=260100) it else it.substring(2) } "${mc}.${version}" }, From 2afc80976dd6ee37d48f8b086c5ca8ec263c41ca Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 17:16:46 +0700 Subject: [PATCH 06/92] ci: Update mc-runtime-test --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8d62506c..0b89aa1a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,7 +60,7 @@ jobs: - name: Retrieve JSON run: | curl -Ls -o "headlessmc.json" "https://api.github.com/repos/3arthqu4ke/headlessmc/releases/tags/2.7.1" --header "Authorization: ${{ secrets.GITHUB_TOKEN }}" - curl -Ls -o "mc-runtime-test.json" "https://api.github.com/repos/null2264/mc-runtime-test/releases/tags/5.2.3" --header "Authorization: ${{ secrets.GITHUB_TOKEN }}" + curl -Ls -o "mc-runtime-test.json" "https://api.github.com/repos/null2264/mc-runtime-test/releases/tags/5.2.5" --header "Authorization: ${{ secrets.GITHUB_TOKEN }}" - name: Upload jar files uses: actions/upload-artifact@v4 From c301e1076339485399c87a693e9a0d85eb920f2a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 19:35:25 +0700 Subject: [PATCH 07/92] chore(deps): 26.1 uses Java 25 --- build.gradle.kts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index b59e8506..53e1a1e7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -297,7 +297,13 @@ subprojects { } val targetJavaVersion = if (!isApi) { - if (mcVersion >= 12006) 21 else (if (mcVersion >= 11700) 17 else 8) + when (mcVersion) { + in 11200..11605 -> 8 + in 11700..11701 -> 16 + in 11800..12004 -> 17 + in 12005..12111 -> 21 + else -> 25 + } } else { 8 // APIs should always target Java 8 } From 927269074d3943b4c58e8207724a73b5fa79d40e Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 20:42:06 +0700 Subject: [PATCH 08/92] fix(deps): Update fabric loader to v0.18.4 --- cobblegen/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 6a86bfb5..2a9b88c8 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -77,7 +77,7 @@ loom { dependencies { if (isFabric) { - modImplementation("net.fabricmc:fabric-loader:0.17.2") + modImplementation("net.fabricmc:fabric-loader:0.18.4") // Mainly for testing // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env From 17fa3fb477e2b7a63ca68e036cdda26c09d06e39 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 20:43:54 +0700 Subject: [PATCH 09/92] fix: Use the correct version code format --- buildSrc/src/main/kotlin/VersionRange.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/VersionRange.kt b/buildSrc/src/main/kotlin/VersionRange.kt index 7a54f419..fd05bcc1 100644 --- a/buildSrc/src/main/kotlin/VersionRange.kt +++ b/buildSrc/src/main/kotlin/VersionRange.kt @@ -72,7 +72,7 @@ fun supportedVersionRange(mcVersion: Int, loader: String): VersionRange { in 12102..12104 -> VersionRange("1.21.1", "1.21.4") in 12105..12110 -> VersionRange("1.21.4", "1.21.10") 12111 -> VersionRange("1.21.10", "1.21.11") - 22601 -> VersionRange("1.21.11", null) + 260100 -> VersionRange("1.21.11", null) else -> VersionRange(null, null) } } From a967aba5929b2a1511644e992bd36218c09c3512 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 22:05:10 +0700 Subject: [PATCH 10/92] fix(buildSrc): Support snapshot --- build.gradle.kts | 4 ++-- buildSrc/src/main/kotlin/VersionRange.kt | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 53e1a1e7..da99a1a6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -347,7 +347,7 @@ subprojects { publishMods { val mainProject = project(":cobblegen") file.set(mainProject.file("build/libs/${rootProject.properties["archives_base_name"]}-${mainProject.version}.jar")) - val releaseVersions = mcVersions(versionRange, filters = listOf("release")) + val releaseVersions = mcVersions(versionRange) displayName.set( buildString { append("[") @@ -357,7 +357,7 @@ publishMods { if (isNeo) append("NEOFORGE") else append("FORGE") } append(" MC") - append(releaseVersions[0]) + append(releaseVersions.getOrNull() ?: "0.0.0") if (releaseVersions.size > 1) append("+") append("]") append(" v") diff --git a/buildSrc/src/main/kotlin/VersionRange.kt b/buildSrc/src/main/kotlin/VersionRange.kt index fd05bcc1..1106d79a 100644 --- a/buildSrc/src/main/kotlin/VersionRange.kt +++ b/buildSrc/src/main/kotlin/VersionRange.kt @@ -21,6 +21,7 @@ data class VersionRange( val to: String?, val inclusiveFrom: Boolean = false, val inclusiveTo: Boolean = true, + val isSnapshot: Boolean = false, ) { val fromSanitized: String? get() = from?.replace(".x", ".9999", true) val toSanitized: String? get() = to?.replace(".x", ".9999", true) @@ -72,7 +73,7 @@ fun supportedVersionRange(mcVersion: Int, loader: String): VersionRange { in 12102..12104 -> VersionRange("1.21.1", "1.21.4") in 12105..12110 -> VersionRange("1.21.4", "1.21.10") 12111 -> VersionRange("1.21.10", "1.21.11") - 260100 -> VersionRange("1.21.11", null) + 260100 -> VersionRange("1.21.11", null, isSnapshot = true) else -> VersionRange(null, null) } } @@ -92,7 +93,12 @@ fun Version.toMojangString(): String = "$major.$minor${if (patch > 0) ".$patch" else ""}${preRelease?.let { "-$preRelease" } ?: ""}" + (buildMetadata?.let { "+$buildMetadata" } ?: "") -fun mcVersions(target: VersionRange, filters: List = listOf("release", "snapshot")): List { +fun mcVersions(target: VersionRange): List { + val filters = buildList { + add("release") + if (target.isSnapshot) add("snapshot") + } + val client = HttpClient.newHttpClient() // TODO: Caching this is probably a good idea... val response = client.send( From 26522d9d3b25259f567812967389433029599bdb Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 22:05:59 +0700 Subject: [PATCH 11/92] fix: List.get --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index da99a1a6..c9989225 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -357,7 +357,7 @@ publishMods { if (isNeo) append("NEOFORGE") else append("FORGE") } append(" MC") - append(releaseVersions.getOrNull() ?: "0.0.0") + append(releaseVersions[0]) if (releaseVersions.size > 1) append("+") append("]") append(" v") From 8fd5991235a52a1b1786da8e18f2711e7e587455 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 7 Jan 2026 22:18:59 +0700 Subject: [PATCH 12/92] fix: 26.1 use Java 25 --- .github/workflows/build.yml | 1 + versions.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b89aa1a..acc10d57 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,6 +98,7 @@ jobs: 8 17 21 + 25 gradle-no-cache-if: true - name: Setup properties diff --git a/versions.json b/versions.json index 5d11bec8..3cd4874f 100644 --- a/versions.json +++ b/versions.json @@ -34,7 +34,7 @@ { "mc": "1.21.11", "loader": "fabric", "java": "21", "testVersions": ["1.21.11"] }, { "mc": "1.21.11", "loader": "neoforge", "java": "21", "testVersions": ["1.21.11"] }, - { "mc": "26.1", "loader": "fabric", "java": "21", "testVersions": ["26.1"] }, - { "mc": "26.1", "loader": "neoforge", "java": "21", "testVersions": ["26.1"] } + { "mc": "26.1", "loader": "fabric", "java": "25", "testVersions": ["26.1"] }, + { "mc": "26.1", "loader": "neoforge", "java": "25", "testVersions": ["26.1"] } ] } From 5ddd75bea96a8579e1fc180126574b30450705cd Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 08:07:36 +0700 Subject: [PATCH 13/92] chore(deps): Update gradle to v9.2.1 To support Java 25 --- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 45633 bytes gradle/wrapper/gradle-wrapper.properties | 8 +- gradlew | 12 +- gradlew.bat | 187 +++++++++++------------ 4 files changed, 104 insertions(+), 103 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..f8e1ee3125fe0768e9a76ee977ac089eb657005e 100644 GIT binary patch literal 45633 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�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 literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0ceb5e90..23449a2b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1 +1,7 @@ -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index f5feea6d..adff685a 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a218..e509b2dd 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,94 +1,93 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 496ae774a1826bb95c41f426e5bfa54acf318aa7 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 08:09:07 +0700 Subject: [PATCH 14/92] fix: Force java version on RunGame task --- cobblegen/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 2a9b88c8..9f0a2204 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -75,6 +75,10 @@ loom { } } +tasks.withType().configureEach { + javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) +} + dependencies { if (isFabric) { modImplementation("net.fabricmc:fabric-loader:0.18.4") From be0489750477909d698dcbba4214f5e6ca90ce64 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 08:17:24 +0700 Subject: [PATCH 15/92] fix: Remove mappings for MC 26.1 Since MC 26.1 and newer will no longer be obfuscated --- build.gradle.kts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c9989225..d437a17e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -139,9 +139,12 @@ subprojects { else common(listOf(loaderName)) } - val loom = project.extensions["loom"] as LoomGradleExtension - loom.apply { - silentMojangMappingsLicense() + + if (mcVersion < 260100) { + val loom = project.extensions["loom"] as LoomGradleExtension + loom.apply { + silentMojangMappingsLicense() + } } } @@ -191,7 +194,9 @@ subprojects { val mappings by configurations minecraft(MC.versioned(mcVersion)) - mappings(loom.officialMojangMappings()) + if (mcVersion < 260100) { + mappings(loom.officialMojangMappings()) + } } shade("blue.endless:jankson:${project.properties["jankson_version"]}") From 496ad35dafad9f9d8f9064b626a8a462d0a2b76f Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 11:44:48 +0700 Subject: [PATCH 16/92] refactor(mclib): Back to using sponge's gradle --- build.gradle.kts | 22 ++++++---------------- mclib/build.gradle.kts | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d437a17e..cd162143 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -118,8 +118,6 @@ subprojects { // NOTE: This here for when I finally split the API to its own module, hopefully on v6.0 val isApi = false; // APIs shouldn't contain anything Minecraft related val isModModule = project == project(":cobblegen") - // Modules that contains MC-related stuff - val isMcModule = isModModule || project == project(":mclib") apply(plugin = "java") apply(plugin = "com.gradleup.shadow") @@ -127,18 +125,10 @@ subprojects { if (isModModule) { // NOTE: This must be set before archloom is applied! extra.set("loom.platform", loaderName) - } - - if (isMcModule) { apply(plugin = "architectury-plugin") apply(plugin = "io.github.null2264.architectury-loom") val arch = project.extensions["architectury"] as ArchitectPluginExtension - arch.apply { - if (isModModule) - loader(loaderName) - else - common(listOf(loaderName)) - } + arch.loader(loaderName) if (mcVersion < 260100) { val loom = project.extensions["loom"] as LoomGradleExtension @@ -182,14 +172,14 @@ subprojects { } val loom by lazy { - if (!isMcModule) { - throw IllegalStateException("Loom only available for MC modules") + if (!isModModule) { + throw IllegalStateException("Loom only available for mod modules") } project.the() } dependencies { - if (isMcModule) { + if (isModModule) { val minecraft by configurations val mappings by configurations @@ -207,8 +197,8 @@ subprojects { if (isModModule) { compileOnly(project(":stubs")) - compileInternal(project(":mclib", configuration = "namedElements")) { isTransitive = false } - shadeInternal(project(":mclib", configuration = "transformProduction$loaderProd")) { + compileInternal(project(":mclib")) { isTransitive = false } + shadeInternal(project(":mclib")) { // Remove Junit test libraries exclude(group = "org.junit.jupiter", module = "junit-jupiter") exclude(group = "org.junit.jupiter", module = "junit-jupiter-engine") diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index b464b761..71bc0b35 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -1,6 +1,17 @@ +plugins { + id("org.spongepowered.gradle.vanilla") version "0.2.1-SNAPSHOT" +} + +minecraft { + version(project.ext["mcVersionStr"] as String) +} + +repositories { + maven("https://repo.spongepowered.org/maven/") +} + dependencies { - // Mostly for Mixin and Arch's dependant on Fabric's @Environment annotations - modCompileOnly("net.fabricmc:fabric-loader:0.17.2") + compileOnly("org.spongepowered:mixin:0.8.5") } publishing { From f004e2a8ea99a97049c7271d302c77c664c9c18c Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 11:54:04 +0700 Subject: [PATCH 17/92] fix(deps): Update shadow --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index e052f1c9..c7da4fc5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,7 +19,7 @@ pluginManagement { } } plugins { - id("com.gradleup.shadow") version "8.3.5" + id("com.gradleup.shadow") version "9.3.1" id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" } } From d443f79d6ca2727bc58f475bdedd65d0f7f39065 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 12:33:48 +0700 Subject: [PATCH 18/92] fix(deps): Update spongegradle --- mclib/build.gradle.kts | 5 ++++- stubs/build.gradle.kts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 71bc0b35..adc25865 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -1,5 +1,8 @@ plugins { - id("org.spongepowered.gradle.vanilla") version "0.2.1-SNAPSHOT" + id("org.spongepowered.gradle.vanilla") version when(project.ext["mcVersion"] as Int) { + in 11605..12111 -> "0.2.2-SNAPSHOT" + else -> "0.3.0-SNAPSHOT" + } } minecraft { diff --git a/stubs/build.gradle.kts b/stubs/build.gradle.kts index 78857248..d8885592 100644 --- a/stubs/build.gradle.kts +++ b/stubs/build.gradle.kts @@ -1,5 +1,8 @@ plugins { - id("org.spongepowered.gradle.vanilla") version "0.2.1-SNAPSHOT" + id("org.spongepowered.gradle.vanilla") version when(project.ext["mcVersion"] as Int) { + in 11605..12111 -> "0.2.2-SNAPSHOT" + else -> "0.3.0-SNAPSHOT" + } } minecraft { From c9ef27a42fe2a4510c3c7162920846534eabd5be Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 12:51:09 +0700 Subject: [PATCH 19/92] fix: Gradle pain --- mclib/build.gradle.kts | 5 +---- settings.gradle.kts | 14 ++++++++++++-- stubs/build.gradle.kts | 5 +---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index adc25865..8f01b268 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -1,8 +1,5 @@ plugins { - id("org.spongepowered.gradle.vanilla") version when(project.ext["mcVersion"] as Int) { - in 11605..12111 -> "0.2.2-SNAPSHOT" - else -> "0.3.0-SNAPSHOT" - } + id("org.spongepowered.gradle.vanilla") } minecraft { diff --git a/settings.gradle.kts b/settings.gradle.kts index c7da4fc5..a49aef76 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,11 +10,21 @@ pluginManagement { maven("https://repo.spongepowered.org/maven/") gradlePluginPortal() } + val mcVer: String by settings + val (major, minor, patch) = mcVer + .split(".") + .toMutableList() + .apply { while (this.size < 3) this.add("") } + val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() + resolutionStrategy { eachPlugin { if (requested.id.id == "org.spongepowered.gradle.vanilla") { - // REF: https://repo.spongepowered.org/#browse/browse:maven-public:org%2Fspongepowered%2Fvanillagradle%2F0.2.1-SNAPSHOT - useModule("org.spongepowered:vanillagradle:0.2.1-20240507.024226-82") + val targetModule = when (mcVersion) { + in 11605..12111 -> "org.spongepowered:vanillagradle:0.2.1-SNAPSHOT" + else -> "org.spongepowered:vanillagradle:0.3.0-SNAPSHOT" + } + useModule(targetModule) } } } diff --git a/stubs/build.gradle.kts b/stubs/build.gradle.kts index d8885592..7ac407db 100644 --- a/stubs/build.gradle.kts +++ b/stubs/build.gradle.kts @@ -1,8 +1,5 @@ plugins { - id("org.spongepowered.gradle.vanilla") version when(project.ext["mcVersion"] as Int) { - in 11605..12111 -> "0.2.2-SNAPSHOT" - else -> "0.3.0-SNAPSHOT" - } + id("org.spongepowered.gradle.vanilla") } minecraft { From 0215722a3c6a129f4ed576bafc507906adfe600b Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 13:34:33 +0700 Subject: [PATCH 20/92] fix: Accidentally downgrade sponge gradle --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index a49aef76..d4b610c6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,7 +21,7 @@ pluginManagement { eachPlugin { if (requested.id.id == "org.spongepowered.gradle.vanilla") { val targetModule = when (mcVersion) { - in 11605..12111 -> "org.spongepowered:vanillagradle:0.2.1-SNAPSHOT" + in 11605..12111 -> "org.spongepowered:vanillagradle:0.2.2-SNAPSHOT" else -> "org.spongepowered:vanillagradle:0.3.0-SNAPSHOT" } useModule(targetModule) From 3bb86f3afbbf64fb4ab0059fc86c6632f0a7f465 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 15:54:05 +0700 Subject: [PATCH 21/92] fix: Disable obfuscation --- build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index cd162143..877f990b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -125,6 +125,9 @@ subprojects { if (isModModule) { // NOTE: This must be set before archloom is applied! extra.set("loom.platform", loaderName) + if (mcVersion >= 260100) { + extra.set("fabric.loom.disableObfuscation", true) + } apply(plugin = "architectury-plugin") apply(plugin = "io.github.null2264.architectury-loom") val arch = project.extensions["architectury"] as ArchitectPluginExtension From 06125ee9ddf2e9ec67a0bcf2c1011ae3dc6045a2 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 18:39:25 +0700 Subject: [PATCH 22/92] fix: Disable mappings already ffs --- build.gradle.kts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 877f990b..29ac91de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -47,12 +47,16 @@ allprojects { apply(plugin = "java") apply(plugin = "maven-publish") - ext["mcVersion"] = mcVersion - ext["mcVersionStr"] = mcVersionStr - ext["loaderName"] = loaderName - ext["isFabric"] = isFabric - ext["isForge"] = isForge - ext["isNeo"] = isNeo + extra["mcVersion"] = mcVersion + extra["mcVersionStr"] = mcVersionStr + extra["loaderName"] = loaderName + extra["isFabric"] = isFabric + extra["isForge"] = isForge + extra["isNeo"] = isNeo + + if (mcVersion >= 260100) { + extra["fabric.loom.disableObfuscation"] = true + } base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") @@ -125,9 +129,6 @@ subprojects { if (isModModule) { // NOTE: This must be set before archloom is applied! extra.set("loom.platform", loaderName) - if (mcVersion >= 260100) { - extra.set("fabric.loom.disableObfuscation", true) - } apply(plugin = "architectury-plugin") apply(plugin = "io.github.null2264.architectury-loom") val arch = project.extensions["architectury"] as ArchitectPluginExtension @@ -184,10 +185,9 @@ subprojects { dependencies { if (isModModule) { val minecraft by configurations - val mappings by configurations - minecraft(MC.versioned(mcVersion)) if (mcVersion < 260100) { + val mappings by configurations mappings(loom.officialMojangMappings()) } } From 2fbc8594e72f7d010c35af62dd4d03a4edc5b399 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 19:07:35 +0700 Subject: [PATCH 23/92] fix: wtf? --- build.gradle.kts | 4 ---- settings.gradle.kts | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 29ac91de..ed1ed57c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,10 +54,6 @@ allprojects { extra["isForge"] = isForge extra["isNeo"] = isNeo - if (mcVersion >= 260100) { - extra["fabric.loom.disableObfuscation"] = true - } - base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") val buildNumber: String? = System.getenv("GITHUB_RUN_NUMBER") diff --git a/settings.gradle.kts b/settings.gradle.kts index d4b610c6..7fbbc713 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,10 @@ +val mcVer: String by settings +val (major, minor, patch) = mcVer + .split(".") + .toMutableList() + .apply { while (this.size < 3) this.add("") } +val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() + pluginManagement { repositories { maven("https://maven.fabricmc.net/") @@ -10,12 +17,6 @@ pluginManagement { maven("https://repo.spongepowered.org/maven/") gradlePluginPortal() } - val mcVer: String by settings - val (major, minor, patch) = mcVer - .split(".") - .toMutableList() - .apply { while (this.size < 3) this.add("") } - val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() resolutionStrategy { eachPlugin { @@ -34,6 +35,12 @@ pluginManagement { } } +gradle.beforeProject { + if (mcVersion >= 260100) { + extensions.extraProperties["fabric.loom.disableObfuscation"] = true + } +} + rootProject.name = "CobbleGen" include(":mclib") From 28f1a9ae8587dab4122eec7e7cdd1531fdb28023 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 19:12:53 +0700 Subject: [PATCH 24/92] revert: "wtf?" This reverts commit 2fbc8594e72f7d010c35af62dd4d03a4edc5b399. --- build.gradle.kts | 4 ++++ settings.gradle.kts | 19 ++++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ed1ed57c..29ac91de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,6 +54,10 @@ allprojects { extra["isForge"] = isForge extra["isNeo"] = isNeo + if (mcVersion >= 260100) { + extra["fabric.loom.disableObfuscation"] = true + } + base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") val buildNumber: String? = System.getenv("GITHUB_RUN_NUMBER") diff --git a/settings.gradle.kts b/settings.gradle.kts index 7fbbc713..d4b610c6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,10 +1,3 @@ -val mcVer: String by settings -val (major, minor, patch) = mcVer - .split(".") - .toMutableList() - .apply { while (this.size < 3) this.add("") } -val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() - pluginManagement { repositories { maven("https://maven.fabricmc.net/") @@ -17,6 +10,12 @@ pluginManagement { maven("https://repo.spongepowered.org/maven/") gradlePluginPortal() } + val mcVer: String by settings + val (major, minor, patch) = mcVer + .split(".") + .toMutableList() + .apply { while (this.size < 3) this.add("") } + val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() resolutionStrategy { eachPlugin { @@ -35,12 +34,6 @@ pluginManagement { } } -gradle.beforeProject { - if (mcVersion >= 260100) { - extensions.extraProperties["fabric.loom.disableObfuscation"] = true - } -} - rootProject.name = "CobbleGen" include(":mclib") From 0e4fcf4f56a8e91a2cf43368c69a007ac088fbd4 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 8 Jan 2026 19:21:30 +0700 Subject: [PATCH 25/92] fix: wtf??? --- gradle.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle.properties b/gradle.properties index 30289cb4..936eaff6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,6 +32,8 @@ forge.enableGameTest=true neoforge.enableGameTest=true null2264.cobblegen.gametest=true +fabric.loom.disableObfuscation=true + # FIXME: Remove this once ArchLoom is rebased to 1.14 loom.ignoreDependencyLoomVersionValidation=true From 55d372be46d2e5a549bfd5c5b30446defe0659db Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 05:39:02 +0700 Subject: [PATCH 26/92] fix: arch-plugin --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 29ac91de..693f0343 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ import org.apache.tools.ant.filters.StripJavaComments plugins { id("java") - id("architectury-plugin") version "3.4-SNAPSHOT" + id("architectury-plugin") version "3.4.162" id("io.github.null2264.architectury-loom") version "1.13-SNAPSHOT" apply false id("com.gradleup.shadow") apply false id("me.modmuss50.mod-publish-plugin") version "1.1.0" From d2252976122383243e9611f5f02bf1f3c9efc04a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 05:55:37 +0700 Subject: [PATCH 27/92] revert: "arch-plugin" This reverts commit 55d372be46d2e5a549bfd5c5b30446defe0659db. --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 693f0343..29ac91de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ import org.apache.tools.ant.filters.StripJavaComments plugins { id("java") - id("architectury-plugin") version "3.4.162" + id("architectury-plugin") version "3.4-SNAPSHOT" id("io.github.null2264.architectury-loom") version "1.13-SNAPSHOT" apply false id("com.gradleup.shadow") apply false id("me.modmuss50.mod-publish-plugin") version "1.1.0" From 0f54a2f0cd57d8f139e88158cbb9e799636a1ef3 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 05:59:08 +0700 Subject: [PATCH 28/92] fix: Add shedaniel maven --- settings.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index d4b610c6..d8c8c7b6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,6 +2,7 @@ pluginManagement { repositories { maven("https://maven.fabricmc.net/") maven("https://maven.aap.my.id/") // For early access to "unstable" features + maven("https://maven.shedaniel.me/") maven("https://maven.architectury.dev/") maven("https://jitpack.io/") maven("https://files.minecraftforge.net/maven/") From 0afdbcd4157448e7506b6ce3aa27920feed82956 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 06:09:12 +0700 Subject: [PATCH 29/92] fix: wtf??? --- build.gradle.kts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 29ac91de..ea0034e8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,9 +54,7 @@ allprojects { extra["isForge"] = isForge extra["isNeo"] = isNeo - if (mcVersion >= 260100) { - extra["fabric.loom.disableObfuscation"] = true - } + extra["fabric.loom.disableObfuscation"] = true base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") @@ -134,11 +132,9 @@ subprojects { val arch = project.extensions["architectury"] as ArchitectPluginExtension arch.loader(loaderName) - if (mcVersion < 260100) { - val loom = project.extensions["loom"] as LoomGradleExtension - loom.apply { - silentMojangMappingsLicense() - } + val loom = project.extensions["loom"] as LoomGradleExtension + loom.apply { + silentMojangMappingsLicense() } } @@ -186,10 +182,8 @@ subprojects { if (isModModule) { val minecraft by configurations minecraft(MC.versioned(mcVersion)) - if (mcVersion < 260100) { - val mappings by configurations - mappings(loom.officialMojangMappings()) - } + val mappings by configurations + mappings(loom.officialMojangMappings()) } shade("blue.endless:jankson:${project.properties["jankson_version"]}") From 22af9b70125e80b603977467a1446aee1264de84 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 06:19:42 +0700 Subject: [PATCH 30/92] revert: wtf??????? This reverts commit 0afdbcd4157448e7506b6ce3aa27920feed82956. --- build.gradle.kts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ea0034e8..29ac91de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,7 +54,9 @@ allprojects { extra["isForge"] = isForge extra["isNeo"] = isNeo - extra["fabric.loom.disableObfuscation"] = true + if (mcVersion >= 260100) { + extra["fabric.loom.disableObfuscation"] = true + } base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") @@ -132,9 +134,11 @@ subprojects { val arch = project.extensions["architectury"] as ArchitectPluginExtension arch.loader(loaderName) - val loom = project.extensions["loom"] as LoomGradleExtension - loom.apply { - silentMojangMappingsLicense() + if (mcVersion < 260100) { + val loom = project.extensions["loom"] as LoomGradleExtension + loom.apply { + silentMojangMappingsLicense() + } } } @@ -182,8 +186,10 @@ subprojects { if (isModModule) { val minecraft by configurations minecraft(MC.versioned(mcVersion)) - val mappings by configurations - mappings(loom.officialMojangMappings()) + if (mcVersion < 260100) { + val mappings by configurations + mappings(loom.officialMojangMappings()) + } } shade("blue.endless:jankson:${project.properties["jankson_version"]}") From c2049a74a616b35a3fe4c4811664359466fcc497 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 06:22:13 +0700 Subject: [PATCH 31/92] fix: wtf?!! --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 29ac91de..ef8a4a1c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,7 +54,7 @@ allprojects { extra["isForge"] = isForge extra["isNeo"] = isNeo - if (mcVersion >= 260100) { + if (mcVersion < 260100) { extra["fabric.loom.disableObfuscation"] = true } From 7a25ff585b3c6c9aede6df226c6d7e421c2b8e7a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 07:22:06 +0700 Subject: [PATCH 32/92] fix: Yep --- build.gradle.kts | 1 + cobblegen/build.gradle.kts | 38 ++++++++++++++++++++++---------------- gradle.properties | 1 + 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ef8a4a1c..174350c3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -55,6 +55,7 @@ allprojects { extra["isNeo"] = isNeo if (mcVersion < 260100) { + // This somehow enable it instead?!?! WTF?????????? extra["fabric.loom.disableObfuscation"] = true } diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 9f0a2204..887a05e3 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -79,20 +79,24 @@ tasks.withType().configureEach { javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) } +fun DependencyHandlerScope.dep(configuration: String, dependency: String) { + add(configuration.replace("mod", "").replaceFirstChar { it.lowercase(java.util.Locale.getDefault()) }, dependency) +} + dependencies { if (isFabric) { - modImplementation("net.fabricmc:fabric-loader:0.18.4") + dep("modImplementation", "net.fabricmc:fabric-loader:0.18.4") // Mainly for testing // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env // REF: https://github.com/FabricMC/fabric/issues/4491 if (mcVersion in 11606..12104) { - modLocalRuntime(fapi.versioned(mcVersion)) + dep("modLocalRuntime", fapi.versioned(mcVersion)) } else { try { // FIXME: Is Resource Loader even needed? //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) - modLocalRuntime(fapiGameTest.versioned(mcVersion)) + dep("modLocalRuntime", fapiGameTest.versioned(mcVersion)) } catch (e: IllegalStateException) { } } @@ -116,35 +120,37 @@ dependencies { // <- EMI if (mcVersion <= 11802) { - modCompileOnly(emi(mcVersion, null, api = true).versioned(0)) + dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(0)) if (project.properties["recipe_viewer"] == "emi" && isFabric) - modLocalRuntime(emi(mcVersion).versioned(0)) + dep("modLocalRuntime", emi(mcVersion).versioned(0)) } else { - modCompileOnly(emi(mcVersion, loaderName, api = true).versioned(0)) - if (project.properties["recipe_viewer"] == "emi") - modLocalRuntime(emi(mcVersion, loaderName).versioned(0)) + if (mcVersion <= 12105) { + dep("modCompileOnly", emi(mcVersion, loaderName, api = true).versioned(0)) + if (project.properties["recipe_viewer"] == "emi") + dep("modLocalRuntime", emi(mcVersion, loaderName).versioned(0)) + } } // EMI -> // <- REI // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* - modCompileOnly(rei(loaderName, true).versioned(mcVersion)) + dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) if (mcVersion in 12002..12104) { // FIXME: Not sure why it's not included - modCompileOnly("me.shedaniel.cloth:basic-math:0.6.1") - modCompileOnly("dev.architectury:architectury:11.1.13") + dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") + dep("modCompileOnly", "dev.architectury:architectury:11.1.13") } if (project.properties["recipe_viewer"] == "rei") { if (mcVersion == 11902) // REI's stupid dep bug - modLocalRuntime("dev.architectury:architectury-fabric:6.5.77") - modLocalRuntime(rei(loaderName).versioned(mcVersion)) + dep("modLocalRuntime", "dev.architectury:architectury-fabric:6.5.77") + dep("modLocalRuntime", rei(loaderName).versioned(mcVersion)) } // REI -> // <- JEI - modCompileOnly(jei(mcVersion, loaderName, common = true, api = true).versioned(0)) - modCompileOnly(jei(mcVersion, loaderName, common = false, api = true).versioned(0)) + dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(0)) + dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(0)) if (project.properties["recipe_viewer"] == "jei") - modCompileOnly(jei(mcVersion, loaderName, common = false, api = false).versioned(0)) + dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(0)) // JEI -> /* FIXME: Broken, somehow diff --git a/gradle.properties b/gradle.properties index 936eaff6..d786bd45 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,6 +32,7 @@ forge.enableGameTest=true neoforge.enableGameTest=true null2264.cobblegen.gametest=true +# Setting this true by default since setting it to true through gradle dsl caused it to become false FOR GOD KNOWS WHY fabric.loom.disableObfuscation=true # FIXME: Remove this once ArchLoom is rebased to 1.14 From b7746621db65a9c7da1e14761809c6a7d3bdadf2 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 09:56:14 +0700 Subject: [PATCH 33/92] fix: Import Locale --- cobblegen/build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 887a05e3..d67d75a1 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -1,6 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dependencies.* import net.fabricmc.loom.task.RemapJarTask +import java.util.Locale plugins { } @@ -80,7 +81,7 @@ tasks.withType().configureEach { } fun DependencyHandlerScope.dep(configuration: String, dependency: String) { - add(configuration.replace("mod", "").replaceFirstChar { it.lowercase(java.util.Locale.getDefault()) }, dependency) + add(configuration.replace("mod", "").replaceFirstChar { it.lowercase(Locale.getDefault()) }, dependency) } dependencies { From e143b8274c9b63c8b641ed0d187e43df508e3f7f Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 10:04:27 +0700 Subject: [PATCH 34/92] fix: Don't remap jar for 26.1 --- cobblegen/build.gradle.kts | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index d67d75a1..1328c0d5 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -81,7 +81,16 @@ tasks.withType().configureEach { } fun DependencyHandlerScope.dep(configuration: String, dependency: String) { - add(configuration.replace("mod", "").replaceFirstChar { it.lowercase(Locale.getDefault()) }, dependency) + add( + configuration.let { + if (mcVersion < 260100) { + it + } else { + it.replace("mod", "").replaceFirstChar { it.lowercase(Locale.getDefault()) } + } + }, + dependency, + ) } dependencies { @@ -164,13 +173,15 @@ dependencies { } } -val remapJar by tasks.getting(RemapJarTask::class) { - val shadowJar by tasks.getting(ShadowJar::class) - dependsOn(shadowJar) - if (isForge && mcVersion >= 12105) { - atAccessWideners.add("cobblegen.accesswidener") +if (mcVersion < 260100) { + val remapJar by tasks.getting(RemapJarTask::class) { + val shadowJar by tasks.getting(ShadowJar::class) + dependsOn(shadowJar) + if (isForge && mcVersion >= 12105) { + atAccessWideners.add("cobblegen.accesswidener") + } + inputFile.set(shadowJar.archiveFile) } - inputFile.set(shadowJar.archiveFile) } //val deleteResources by tasks.creating(Delete::class) { From 182e8cb515d533c1004a2f9e9435ce7f935d257b Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 10:22:00 +0700 Subject: [PATCH 35/92] fix: 26.1-snapshot-2 --- buildSrc/src/main/kotlin/dependencies/Minecraft.kt | 2 +- mclib/build.gradle.kts | 4 +++- stubs/build.gradle.kts | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt index a8726c6a..068c4c9a 100644 --- a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt +++ b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt @@ -7,7 +7,7 @@ val minecraft = Dependency( when (mcVersion) { // For snapshots //12100 -> "some snapshot" - 260100 -> "26.1-snapshot-1" + 260100 -> "26.1-snapshot-2" else -> versionStr(mcVersion) } }, diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 8f01b268..240ba377 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -1,9 +1,11 @@ +import dependencies.minecraft as MC + plugins { id("org.spongepowered.gradle.vanilla") } minecraft { - version(project.ext["mcVersionStr"] as String) + version(MC.versioned(project.ext["mcVersion"] as Int)) } repositories { diff --git a/stubs/build.gradle.kts b/stubs/build.gradle.kts index 7ac407db..6ba44d02 100644 --- a/stubs/build.gradle.kts +++ b/stubs/build.gradle.kts @@ -1,10 +1,12 @@ +import dependencies.minecraft as MC + plugins { id("org.spongepowered.gradle.vanilla") } minecraft { //accessWideners(project(":mclib").file("")) - version(project.ext["mcVersionStr"] as String) + version(MC.versioned(project.ext["mcVersion"] as Int)) } repositories { From 9b605ff632390457d1324ce7ec36b48792806b0a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 10:35:54 +0700 Subject: [PATCH 36/92] fix: Use the unformatted one --- build.gradle.kts | 2 +- buildSrc/src/main/kotlin/dependencies/Dependencies.kt | 2 +- mclib/build.gradle.kts | 2 +- stubs/build.gradle.kts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 174350c3..dedde53e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,7 @@ fun setupPreprocessor() { setupPreprocessor() architectury { - minecraft = MC.versioned(mcVersion) + minecraft = MC.version(mcVersion) } allprojects { diff --git a/buildSrc/src/main/kotlin/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/dependencies/Dependencies.kt index 7acba737..ac8ee8bb 100644 --- a/buildSrc/src/main/kotlin/dependencies/Dependencies.kt +++ b/buildSrc/src/main/kotlin/dependencies/Dependencies.kt @@ -3,7 +3,7 @@ package dependencies data class Dependency( private val group: String, private val name: String, - private val version: (Int) -> String, + val version: (Int) -> String, ) { fun versioned(mcVersion: Int): String = "${group}:${name}:${version(mcVersion)}" } diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 240ba377..22f8cc04 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } minecraft { - version(MC.versioned(project.ext["mcVersion"] as Int)) + version(MC.version(project.ext["mcVersion"] as Int)) } repositories { diff --git a/stubs/build.gradle.kts b/stubs/build.gradle.kts index 6ba44d02..7a7f845d 100644 --- a/stubs/build.gradle.kts +++ b/stubs/build.gradle.kts @@ -6,7 +6,7 @@ plugins { minecraft { //accessWideners(project(":mclib").file("")) - version(MC.versioned(project.ext["mcVersion"] as Int)) + version(MC.version(project.ext["mcVersion"] as Int)) } repositories { From 390ec7b87ae3f068ae77b0e4fc062ddc101197b9 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 12:17:40 +0700 Subject: [PATCH 37/92] chore: Default to 26.1 fabric --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index d786bd45..0cc6d5b4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,8 +26,8 @@ create_version_1_18_2=0.5.1-f-build.1333+mc1.18.2 port_lib_version_1_18_2=1.2.869-beta+1.18.2 # Default MC version and loader name for IDEs, will be overwritten by gradle build argument -PmcVer or -PloaderName -mcVer=1.21.11 -null2264.platform=neoforge +mcVer=26.1 +null2264.platform=fabric forge.enableGameTest=true neoforge.enableGameTest=true null2264.cobblegen.gametest=true From 6c33a70704e6ff71c55a233966803263b3db8ccd Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 9 Jan 2026 12:34:46 +0700 Subject: [PATCH 38/92] ci: Use Microsoft's JDK In case they did some bullshit in their distro --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index acc10d57..f65b68dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -93,7 +93,7 @@ jobs: - name: Setup Gradle uses: null2264/actions/gradle-java-setup@363cb9cf3d66bd9c72ed6860142c6b2c121d7e94 with: - distro: temurin + distro: microsoft java: | 8 17 From d0e08b4754cde98d0d813963d41ba8ff0c7e5340 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 10 Jan 2026 19:39:21 +0700 Subject: [PATCH 39/92] revert: "Use Microsoft's JDK" This reverts commit 6c33a70704e6ff71c55a233966803263b3db8ccd. I forgot they don't provide Java 8 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f65b68dd..acc10d57 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -93,7 +93,7 @@ jobs: - name: Setup Gradle uses: null2264/actions/gradle-java-setup@363cb9cf3d66bd9c72ed6860142c6b2c121d7e94 with: - distro: microsoft + distro: temurin java: | 8 17 From b7540870c1affa4c92ccd143cdadf21bf2900859 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Tue, 20 Jan 2026 12:30:34 +0700 Subject: [PATCH 40/92] fix: Don't enable EMI just yet --- .../null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java | 3 ++- .../integration/viewer/emi/FluidInteractionRecipe.java | 3 ++- .../null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java | 3 ++- .../integration/viewer/rei/FluidInteractionCategory.java | 3 ++- .../integration/viewer/rei/FluidInteractionRecipe.java | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java index 49a299c7..02bb4f68 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java +++ b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java @@ -1,4 +1,5 @@ -#if (FABRIC && MC>11605 && MC<=11802) || (MC>=11900 && MC<12111) || MC>=22601 +#if (FABRIC && MC>11605 && MC<=11802) || (MC>=11900 && MC<12111) +// || MC>=22601 package io.github.null2264.cobblegen.integration.viewer.emi; // FIXME: Enable EMI integration for 1.21.11+ when EMI is updated // UPDATE: Looks like EMI won't be updated to 1.21.11 and probably skip to 26.1 diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java index 2ded7549..6536541b 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java +++ b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java @@ -1,4 +1,5 @@ -#if (FABRIC && MC>11605 && MC<=11802) || (MC>=11900 && MC<12111) || MC>=22601 +#if (FABRIC && MC>11605 && MC<=11802) || (MC>=11900 && MC<12111) +// || MC>=22601 package io.github.null2264.cobblegen.integration.viewer.emi; // FIXME: Enable EMI integration for 1.21.11+ when EMI is updated // UPDATE: Looks like EMI won't be updated to 1.21.11 and probably skip to 26.1 diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java index 498db1ae..7719a098 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java +++ b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java @@ -1,4 +1,5 @@ -#if MC>11605 && MC<12111 +#if (MC>11605 && MC<12111) +//|| MC>=260100 package io.github.null2264.cobblegen.integration.viewer.rei; // FIXME: Enable REI integration for 1.21.11 when REI is updated // REF: https://github.com/shedaniel/RoughlyEnoughItems/pull/1989 diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java index a909d824..e8fb2737 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java +++ b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java @@ -1,4 +1,5 @@ -#if MC>11605 && MC<12111 +#if (MC>11605 && MC<12111) +//|| MC>=260100 package io.github.null2264.cobblegen.integration.viewer.rei; // FIXME: Enable REI integration for 1.21.11 when REI is updated // REF: https://github.com/shedaniel/RoughlyEnoughItems/pull/1989 diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java index 3f7d3cd5..d1540a2a 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java +++ b/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java @@ -1,4 +1,5 @@ -#if MC>11605 && MC<12111 +#if (MC>11605 && MC<12111) +//|| MC>=260100 package io.github.null2264.cobblegen.integration.viewer.rei; // FIXME: Enable REI integration for 1.21.11 when REI is updated // REF: https://github.com/shedaniel/RoughlyEnoughItems/pull/1989 From acb633af4d9395720ba051117f587808bc51980f Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Tue, 20 Jan 2026 12:55:57 +0700 Subject: [PATCH 41/92] fix: Mixin is missing for Fabric 26.1, hopefully runtime is fine --- cobblegen/build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 1328c0d5..d5aaba9a 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -110,6 +110,11 @@ dependencies { } catch (e: IllegalStateException) { } } + + if (mcVersion >= 260100) { + // FIXME: For some reason mixin is missing? + dep("compileOnly", "org.spongepowered:mixin:0.8.7") + } } else { if (!isNeo) { "forge"(lexForge.versioned(mcVersion)) From c322b17f5c11f0f4cb4da786fed1c830cbfc3dd6 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 11:30:22 +0700 Subject: [PATCH 42/92] refactor: WIP migration to MDG 1.16.5 will be handled by Arch Loom while the rest will be handled by its respecting gradle plugins, except for 1.20.2-1.20.6 since they're at a limbo state where MDG didn't support it and LegacyMDG didn't support it. --- build.gradle.kts | 62 ++++++++++++++++-------- buildSrc/src/main/kotlin/GradlePlugin.kt | 10 ++++ cobblegen/build.gradle.kts | 44 ++++++++++++++--- gradle.properties | 5 +- 4 files changed, 89 insertions(+), 32 deletions(-) create mode 100644 buildSrc/src/main/kotlin/GradlePlugin.kt diff --git a/build.gradle.kts b/build.gradle.kts index dedde53e..f69c205b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,12 @@ import org.apache.tools.ant.filters.StripJavaComments plugins { id("java") - id("architectury-plugin") version "3.4-SNAPSHOT" - id("io.github.null2264.architectury-loom") version "1.13-SNAPSHOT" apply false + id("architectury-plugin") version "3.4-SNAPSHOT" apply false + id(GradlePlugin.ArchLoom.id) version "1.13-SNAPSHOT" apply false + id(GradlePlugin.Loom.id) version "1.15-SNAPSHOT" apply false + id(GradlePlugin.LegacyLoom.id) version "1.15-SNAPSHOT" apply false + id(GradlePlugin.MDG.id) version "2.0.140" apply false + id(GradlePlugin.LegacyMDG.id) version "2.0.140" apply false id("com.gradleup.shadow") apply false id("me.modmuss50.mod-publish-plugin") version "1.1.0" } @@ -27,6 +31,26 @@ val (major, minor, patch) = mcVersionStr val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() val versionRange = supportedVersionRange(mcVersion, loaderName) +/** + * We're using LegacyMDG instead of ForgeGradle because they provide similar API to Loom instead of the atrocious "fg.deobf" + */ +val projectPlugin = when { + // LegacyMDG only support 1.17 up to 1.20.1 + mcVersion <= 11605 -> GradlePlugin.ArchLoom + isForge -> { + assert(mcVersion <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } + GradlePlugin.LegacyMDG + } + isNeo -> when { + mcVersion <= 12001 -> GradlePlugin.LegacyMDG + // 1.20.2+ is in some kind of limbo for whatever reason, not supported by MDG and not supported by LegacyMDG. + mcVersion in 12002..12006 -> GradlePlugin.ArchLoom + else -> GradlePlugin.MDG + } + isFabric -> if (mcVersion <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom + else -> throw IllegalStateException() +} + fun setupPreprocessor() { val buildProps = buildString { append("# DON'T TOUCH THIS FILE, This is handled by the build script\n") @@ -39,10 +63,6 @@ fun setupPreprocessor() { } setupPreprocessor() -architectury { - minecraft = MC.version(mcVersion) -} - allprojects { apply(plugin = "java") apply(plugin = "maven-publish") @@ -53,11 +73,7 @@ allprojects { extra["isFabric"] = isFabric extra["isForge"] = isForge extra["isNeo"] = isNeo - - if (mcVersion < 260100) { - // This somehow enable it instead?!?! WTF?????????? - extra["fabric.loom.disableObfuscation"] = true - } + extra["projectPlugin"] = projectPlugin base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") @@ -129,13 +145,17 @@ subprojects { if (isModModule) { // NOTE: This must be set before archloom is applied! - extra.set("loom.platform", loaderName) - apply(plugin = "architectury-plugin") - apply(plugin = "io.github.null2264.architectury-loom") - val arch = project.extensions["architectury"] as ArchitectPluginExtension - arch.loader(loaderName) + if (projectPlugin is GradlePlugin.ArchLoom) { + extra.set("loom.platform", loaderName) + apply(plugin = "architectury-plugin") + } + apply(plugin = projectPlugin.id) + if (projectPlugin is GradlePlugin.ArchLoom) { + val arch = project.extensions["architectury"] as ArchitectPluginExtension + arch.loader(loaderName) + } - if (mcVersion < 260100) { + if (projectPlugin.isLegacyLoom()) { val loom = project.extensions["loom"] as LoomGradleExtension loom.apply { silentMojangMappingsLicense() @@ -161,7 +181,7 @@ subprojects { val compileInternal: Configuration by configurations.creating { configurations.compileClasspath.get().extendsFrom(this) configurations.runtimeClasspath.get().extendsFrom(this) - if (isModModule) { + if (isModModule && projectPlugin is GradlePlugin.ArchLoom) { configurations["development$loaderProd"].extendsFrom(this) } } @@ -172,7 +192,7 @@ subprojects { configurations.testAnnotationProcessor.get().extendsFrom(this) } - if (isModModule && !isFabric) { + if (isModModule && projectPlugin is GradlePlugin.ArchLoom) { configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) } @@ -186,8 +206,8 @@ subprojects { dependencies { if (isModModule) { val minecraft by configurations - minecraft(MC.versioned(mcVersion)) - if (mcVersion < 260100) { + minecraft((if (projectPlugin is GradlePlugin.ArchLoom) "" else "com.mojang:minecraft:") + MC.version(mcVersion)) + if (projectPlugin.isLegacyLoom()) { val mappings by configurations mappings(loom.officialMojangMappings()) } diff --git a/buildSrc/src/main/kotlin/GradlePlugin.kt b/buildSrc/src/main/kotlin/GradlePlugin.kt new file mode 100644 index 00000000..dd7258bd --- /dev/null +++ b/buildSrc/src/main/kotlin/GradlePlugin.kt @@ -0,0 +1,10 @@ +sealed class GradlePlugin(val id: String, val isLegacy: Boolean) { + object LegacyLoom : GradlePlugin("net.fabricmc.fabric-loom-remap", true) + object Loom : GradlePlugin("net.fabricmc.fabric-loom", true) + object ArchLoom : GradlePlugin("io.github.null2264.architectury-loom", true) + object MDG : GradlePlugin("net.neoforged.moddev", false) + object LegacyMDG : GradlePlugin("net.neoforged.moddev.legacyforge", true) + + fun isLoom() = this is LegacyLoom || this is Loom || this is ArchLoom + fun isLegacyLoom() = isLoom() && isLegacy +} diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index d5aaba9a..da6a5b7b 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -2,9 +2,8 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dependencies.* import net.fabricmc.loom.task.RemapJarTask import java.util.Locale - -plugins { -} +import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.neoforged.moddevgradle.dsl.NeoForgeExtension val mcVersion = ext["mcVersion"] as Int val mcVersionStr = ext["mcVersionStr"] as String @@ -12,10 +11,19 @@ val loaderName = ext["loaderName"] as String val isFabric = ext["isFabric"] as Boolean val isForge = ext["isForge"] as Boolean val isNeo = ext["isNeo"] as Boolean +val projectPlugin = extra["projectPlugin"] as GradlePlugin group = project.properties["maven_group"] as String -loom { +fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit) { + assert(isLoom()) { "This project didn't use Loom!" } + project.the().configuration() +} +fun GradlePlugin.configureNeo(configuration: NeoForgeExtension.() -> Unit) { + project.the().configuration() +} + +if (projectPlugin.isLoom()) projectPlugin.configureLoom { if (mcVersion >= 12105) { accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") } @@ -74,6 +82,28 @@ loom { ) } } +} else projectPlugin.configureNeo { + // FIXME: Finish this section + version = neoForge.versioned(mcVersion) + + validateAccessTransformers = true + + runs { + named("client") { + gameDirectory.set(rootProject.file("run/client")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") + } + named("server") { + gameDirectory.set(rootProject.file("run/server")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") + } + } + + mods { + register("${base.archivesName.get()}") { + sourceSet(sourceSets.main.get()) + } + } } tasks.withType().configureEach { @@ -83,10 +113,10 @@ tasks.withType().configureEach { fun DependencyHandlerScope.dep(configuration: String, dependency: String) { add( configuration.let { - if (mcVersion < 260100) { + if (projectPlugin.isLegacy) { it } else { - it.replace("mod", "").replaceFirstChar { it.lowercase(Locale.getDefault()) } + it.replace("mod", "").replaceFirstChar { c -> c.lowercase(Locale.getDefault()) } } }, dependency, @@ -115,7 +145,7 @@ dependencies { // FIXME: For some reason mixin is missing? dep("compileOnly", "org.spongepowered:mixin:0.8.7") } - } else { + } else if (projectPlugin.isLoom()) { if (!isNeo) { "forge"(lexForge.versioned(mcVersion)) } else { diff --git a/gradle.properties b/gradle.properties index 0cc6d5b4..50f1e726 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,15 +26,12 @@ create_version_1_18_2=0.5.1-f-build.1333+mc1.18.2 port_lib_version_1_18_2=1.2.869-beta+1.18.2 # Default MC version and loader name for IDEs, will be overwritten by gradle build argument -PmcVer or -PloaderName -mcVer=26.1 +mcVer=1.21.11 null2264.platform=fabric forge.enableGameTest=true neoforge.enableGameTest=true null2264.cobblegen.gametest=true -# Setting this true by default since setting it to true through gradle dsl caused it to become false FOR GOD KNOWS WHY -fabric.loom.disableObfuscation=true - # FIXME: Remove this once ArchLoom is rebased to 1.14 loom.ignoreDependencyLoomVersionValidation=true From f5491fa04c1cc7a8ca3b62412661708b41de462c Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 12:34:57 +0700 Subject: [PATCH 43/92] fix: Loom is not legacy --- buildSrc/src/main/kotlin/GradlePlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/GradlePlugin.kt b/buildSrc/src/main/kotlin/GradlePlugin.kt index dd7258bd..d964c59e 100644 --- a/buildSrc/src/main/kotlin/GradlePlugin.kt +++ b/buildSrc/src/main/kotlin/GradlePlugin.kt @@ -1,6 +1,6 @@ sealed class GradlePlugin(val id: String, val isLegacy: Boolean) { object LegacyLoom : GradlePlugin("net.fabricmc.fabric-loom-remap", true) - object Loom : GradlePlugin("net.fabricmc.fabric-loom", true) + object Loom : GradlePlugin("net.fabricmc.fabric-loom", false) object ArchLoom : GradlePlugin("io.github.null2264.architectury-loom", true) object MDG : GradlePlugin("net.neoforged.moddev", false) object LegacyMDG : GradlePlugin("net.neoforged.moddev.legacyforge", true) From cf2754f22c3897b220e145fbd21ceb953c123050 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 12:38:18 +0700 Subject: [PATCH 44/92] fix: minecraft() is a Loom API --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index f69c205b..f65f1e23 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -204,7 +204,7 @@ subprojects { } dependencies { - if (isModModule) { + if (isModModule && projectPlugin.isLoom()) { val minecraft by configurations minecraft((if (projectPlugin is GradlePlugin.ArchLoom) "" else "com.mojang:minecraft:") + MC.version(mcVersion)) if (projectPlugin.isLegacyLoom()) { From d7883bace3653270e9e123b8f0835b60200426e8 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 12:40:21 +0700 Subject: [PATCH 45/92] fix: forgeRuntimeLibrary only available on Forge-like --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index f65f1e23..8eea4739 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -192,7 +192,7 @@ subprojects { configurations.testAnnotationProcessor.get().extendsFrom(this) } - if (isModModule && projectPlugin is GradlePlugin.ArchLoom) { + if (isModModule && !isFabric && projectPlugin is GradlePlugin.ArchLoom) { configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) } From 68d984e5ab208348125c4b5c2368d7307a083d93 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 12:41:43 +0700 Subject: [PATCH 46/92] fix: .versioned(...) not .version(...) --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8eea4739..950977b8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -206,7 +206,7 @@ subprojects { dependencies { if (isModModule && projectPlugin.isLoom()) { val minecraft by configurations - minecraft((if (projectPlugin is GradlePlugin.ArchLoom) "" else "com.mojang:minecraft:") + MC.version(mcVersion)) + minecraft(MC.versioned(mcVersion)) if (projectPlugin.isLegacyLoom()) { val mappings by configurations mappings(loom.officialMojangMappings()) From 0cce8598c6394b67702c953ed58ee931bf5a15d8 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 13:04:29 +0700 Subject: [PATCH 47/92] fix: Check neo first --- build.gradle.kts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 950977b8..725879fe 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,16 +37,16 @@ val versionRange = supportedVersionRange(mcVersion, loaderName) val projectPlugin = when { // LegacyMDG only support 1.17 up to 1.20.1 mcVersion <= 11605 -> GradlePlugin.ArchLoom - isForge -> { - assert(mcVersion <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } - GradlePlugin.LegacyMDG - } isNeo -> when { mcVersion <= 12001 -> GradlePlugin.LegacyMDG // 1.20.2+ is in some kind of limbo for whatever reason, not supported by MDG and not supported by LegacyMDG. mcVersion in 12002..12006 -> GradlePlugin.ArchLoom else -> GradlePlugin.MDG } + isForge -> { + assert(mcVersion <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } + GradlePlugin.LegacyMDG + } isFabric -> if (mcVersion <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom else -> throw IllegalStateException() } From cc7ceeae87d10b0103717fd05d13d2bbaab29074 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 14:14:28 +0700 Subject: [PATCH 48/92] fix: Rename neoForge to NEO to avoid conflict --- buildSrc/src/main/kotlin/dependencies/NeoForge.kt | 2 +- cobblegen/build.gradle.kts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index 7f88aa1d..16388cff 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -1,6 +1,6 @@ package dependencies -val neoForge = Dependency( +val NEO = Dependency( group = "net.neoforged", name = "neoforge", version = { mcVersion -> diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index da6a5b7b..95eb46af 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -84,7 +84,7 @@ if (projectPlugin.isLoom()) projectPlugin.configureLoom { } } else projectPlugin.configureNeo { // FIXME: Finish this section - version = neoForge.versioned(mcVersion) + version = NEO.versioned(mcVersion) validateAccessTransformers = true @@ -149,7 +149,7 @@ dependencies { if (!isNeo) { "forge"(lexForge.versioned(mcVersion)) } else { - "neoForge"(neoForge.versioned(mcVersion)) + "neoForge"(NEO.versioned(mcVersion)) } } From 441c35636821a42c6be5976999bbedbc69777bb2 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 14:26:58 +0700 Subject: [PATCH 49/92] fix: .version not .versioned --- cobblegen/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 95eb46af..1b7c0ea0 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -84,7 +84,7 @@ if (projectPlugin.isLoom()) projectPlugin.configureLoom { } } else projectPlugin.configureNeo { // FIXME: Finish this section - version = NEO.versioned(mcVersion) + version = NEO.version(mcVersion) validateAccessTransformers = true From 205a045c0ae741b38eecdc109a06f437b72a1d18 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 14:57:44 +0700 Subject: [PATCH 50/92] fix: Create instead of named --- cobblegen/build.gradle.kts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 1b7c0ea0..2890815a 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -89,18 +89,26 @@ if (projectPlugin.isLoom()) projectPlugin.configureLoom { validateAccessTransformers = true runs { - named("client") { + create("client") { + client() gameDirectory.set(rootProject.file("run/client")) ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") } - named("server") { + create("server") { + server() gameDirectory.set(rootProject.file("run/server")) ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") } + create("server") { + type = "gameTestServer" + gameDirectory.set(rootProject.file("run/serverGameTest")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server GameTest") + vmArg("-Dnull2264.cobblegen.gametest=true") + } } mods { - register("${base.archivesName.get()}") { + create("${base.archivesName.get()}") { sourceSet(sourceSets.main.get()) } } From cd3f0d30d238d2de5ce5c696bc5e8c1e59f67db4 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 15:09:09 +0700 Subject: [PATCH 51/92] fix: Fix build --- cobblegen/build.gradle.kts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 2890815a..c13b1f09 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -103,7 +103,10 @@ if (projectPlugin.isLoom()) projectPlugin.configureLoom { type = "gameTestServer" gameDirectory.set(rootProject.file("run/serverGameTest")) ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server GameTest") - vmArg("-Dnull2264.cobblegen.gametest=true") + jvmArgument("-Dnull2264.cobblegen.gametest=true") + systemProperties("$loaderName.enabledGameTestNamespaces", "cobblegen") + systemProperties("$loaderName.gameTestServer", "true") + systemProperties("$loaderName.enableGameTest", "true") } } From 93f4e92246cc5627087f335f316c42bab374c35d Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 15:13:49 +0700 Subject: [PATCH 52/92] fix: Disable IDE run for gametest Should be ran manually --- cobblegen/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index c13b1f09..20a22fc9 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -102,7 +102,7 @@ if (projectPlugin.isLoom()) projectPlugin.configureLoom { create("server") { type = "gameTestServer" gameDirectory.set(rootProject.file("run/serverGameTest")) - ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server GameTest") + ideName.set("") jvmArgument("-Dnull2264.cobblegen.gametest=true") systemProperties("$loaderName.enabledGameTestNamespaces", "cobblegen") systemProperties("$loaderName.gameTestServer", "true") From 6af1fdd6369b8b6279bc32f8afb19fb5e3911d8d Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 19:20:37 +0700 Subject: [PATCH 53/92] fix: Classic plural vs singular --- cobblegen/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 20a22fc9..cf739420 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -104,9 +104,9 @@ if (projectPlugin.isLoom()) projectPlugin.configureLoom { gameDirectory.set(rootProject.file("run/serverGameTest")) ideName.set("") jvmArgument("-Dnull2264.cobblegen.gametest=true") - systemProperties("$loaderName.enabledGameTestNamespaces", "cobblegen") - systemProperties("$loaderName.gameTestServer", "true") - systemProperties("$loaderName.enableGameTest", "true") + systemProperty("$loaderName.enabledGameTestNamespaces", "cobblegen") + systemProperty("$loaderName.gameTestServer", "true") + systemProperty("$loaderName.enableGameTest", "true") } } From dbeda065fdb2eaac237800b976bb35c094e5226e Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 19:46:30 +0700 Subject: [PATCH 54/92] refactor: Simplify configure methods and handle mixin --- cobblegen/build.gradle.kts | 201 +++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 88 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index cf739420..72512470 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -3,7 +3,10 @@ import dependencies.* import net.fabricmc.loom.task.RemapJarTask import java.util.Locale import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.neoforged.moddevgradle.dsl.ModDevExtension import net.neoforged.moddevgradle.dsl.NeoForgeExtension +import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension +import net.neoforged.moddevgradle.legacyforge.dsl.MixinExtension val mcVersion = ext["mcVersion"] as Int val mcVersionStr = ext["mcVersionStr"] as String @@ -15,108 +18,124 @@ val projectPlugin = extra["projectPlugin"] as GradlePlugin group = project.properties["maven_group"] as String -fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit) { +fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit = {}) { assert(isLoom()) { "This project didn't use Loom!" } - project.the().configuration() -} -fun GradlePlugin.configureNeo(configuration: NeoForgeExtension.() -> Unit) { - project.the().configuration() -} + project.the() + .apply { + if (mcVersion >= 12105) { + accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") + } -if (projectPlugin.isLoom()) projectPlugin.configureLoom { - if (mcVersion >= 12105) { - accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") - } + runConfigs { + named("client") { + runDir = "../run/client" + configName = (if (isFabric) "Fabric" else if (!isNeo) "Forge" else "NeoForge") + " Client" + //vmArg("-Dnull2264.cobblegen.gametest=true") + ideConfigGenerated(true) + } + named("server") { + runDir = "../run/server" + configName = (if (isFabric) "Fabric" else if (!isNeo) "Forge" else "NeoForge") + " Server" + //vmArg("-Dnull2264.cobblegen.gametest=true") + ideConfigGenerated(true) + } + register("gametest") { + server() + name("Server GameTest") - runConfigs { - named("client") { - runDir = "../run/client" - configName = (if (isFabric) "Fabric" else if (!isNeo) "Forge" else "NeoForge") + " Client" - //vmArg("-Dnull2264.cobblegen.gametest=true") - ideConfigGenerated(true) - } - named("server") { - runDir = "../run/server" - configName = (if (isFabric) "Fabric" else if (!isNeo) "Forge" else "NeoForge") + " Server" - //vmArg("-Dnull2264.cobblegen.gametest=true") - ideConfigGenerated(true) - } - register("gametest") { - server() - name("Server GameTest") - - vmArg("-Dnull2264.cobblegen.gametest=true") - vmArg("-Dfabric-api.gametest") - vmArg("-Dfabric-api.gametest.report-file=${rootProject.layout.buildDirectory.file("reports/junit.xml").get().getAsFile()}") - // For Forge-alike - property("$loaderName.enabledGameTestNamespaces", "cobblegen") - property("$loaderName.gameTestServer", "true") - property("$loaderName.enableGameTest", "true") - - runDir("../run/serverGameTest") - ideConfigGenerated(false) // Mostly for CI - if (isNeo) { - /* - * Apparently this replicate NeoGradle's - * - * runs { - * gameTest { - * type = "gameTestServer" - * } - * } - */ - environment("gameTestServer") - forgeTemplate("gameTestServer") - if (mcVersion >= 12111) { - // REF: https://github.com/neoforged/NeoForge/blob/af6abbe00ab3071ad58c2cb70b988cb79f0b4af8/buildSrc/src/main/java/net/neoforged/neodev/CreateUserDevConfig.java#L128 - setDefaultMainClass("net.neoforged.fml.startup.GameTestServer") + vmArg("-Dnull2264.cobblegen.gametest=true") + vmArg("-Dfabric-api.gametest") + vmArg("-Dfabric-api.gametest.report-file=${rootProject.layout.buildDirectory.file("reports/junit.xml").get().getAsFile()}") + // For Forge-alike + property("$loaderName.enabledGameTestNamespaces", "cobblegen") + property("$loaderName.gameTestServer", "true") + property("$loaderName.enableGameTest", "true") + + runDir("../run/serverGameTest") + ideConfigGenerated(false) // Mostly for CI + if (isNeo) { + /* + * Apparently this replicate NeoGradle's + * + * runs { + * gameTest { + * type = "gameTestServer" + * } + * } + */ + environment("gameTestServer") + forgeTemplate("gameTestServer") + if (mcVersion >= 12111) { + // REF: https://github.com/neoforged/NeoForge/blob/af6abbe00ab3071ad58c2cb70b988cb79f0b4af8/buildSrc/src/main/java/net/neoforged/neodev/CreateUserDevConfig.java#L128 + defaultMainClass = "net.neoforged.fml.startup.GameTestServer" + } + } } } - } - } - if (!isFabric && !isNeo) { - forge { - mixinConfigs = listOf( - "cobblegen.mixins.json" - ) + if (!isFabric && !isNeo) { + forge { + mixinConfigs = listOf( + "cobblegen.mixins.json" + ) + } + } } - } -} else projectPlugin.configureNeo { - // FIXME: Finish this section - version = NEO.version(mcVersion) + .configuration() +} - validateAccessTransformers = true +inline fun GradlePlugin.configureNeo(configuration: T.() -> Unit = {}) { + project.the() + .apply { + validateAccessTransformers = true - runs { - create("client") { - client() - gameDirectory.set(rootProject.file("run/client")) - ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") - } - create("server") { - server() - gameDirectory.set(rootProject.file("run/server")) - ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") - } - create("server") { - type = "gameTestServer" - gameDirectory.set(rootProject.file("run/serverGameTest")) - ideName.set("") - jvmArgument("-Dnull2264.cobblegen.gametest=true") - systemProperty("$loaderName.enabledGameTestNamespaces", "cobblegen") - systemProperty("$loaderName.gameTestServer", "true") - systemProperty("$loaderName.enableGameTest", "true") - } - } + runs { + create("client") { + client() + gameDirectory.set(rootProject.file("run/client")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") + } + create("server") { + server() + gameDirectory.set(rootProject.file("run/server")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") + } + create("gametest") { + type = "gameTestServer" + gameDirectory.set(rootProject.file("run/serverGameTest")) + ideName.set("") + jvmArgument("-Dnull2264.cobblegen.gametest=true") + systemProperty("$loaderName.enabledGameTestNamespaces", "cobblegen") + systemProperty("$loaderName.gameTestServer", "true") + systemProperty("$loaderName.enableGameTest", "true") + } + } - mods { - create("${base.archivesName.get()}") { - sourceSet(sourceSets.main.get()) + mods { + create("${base.archivesName.get()}") { + sourceSet(sourceSets.main.get()) + } + } } + .configuration() + + // Newer MC handle mixins from (neoforge.)mods.toml file + if (projectPlugin.isLegacy) { + project.the() + .apply { + add(sourceSets.main.get(), "cobblegen.mixins.refmap.json") + config("cobblegen.mixins.json") + } } } +if (projectPlugin.isLoom()) projectPlugin.configureLoom() +else if (projectPlugin.isLegacy) projectPlugin.configureNeo { + version = NEO.version(mcVersion) +} else projectPlugin.configureNeo { + version = NEO.version(mcVersion) +} + tasks.withType().configureEach { javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) } @@ -230,6 +249,12 @@ if (mcVersion < 260100) { } } +val jar by tasks.getting(Jar::class) { + manifest.attributes(mapOf( + "MixinConfigs" to "cobblegen.mixins.json", + )) +} + //val deleteResources by tasks.creating(Delete::class) { // delete(file("build/resources/main")) //} From ddd59a8d90cd1b11ea0fccac6978fe24f683feb1 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 20:03:00 +0700 Subject: [PATCH 55/92] fix: RemapJarTask doesn't exists on MDG --- cobblegen/build.gradle.kts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 72512470..e7ff9942 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -7,6 +7,7 @@ import net.neoforged.moddevgradle.dsl.ModDevExtension import net.neoforged.moddevgradle.dsl.NeoForgeExtension import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension import net.neoforged.moddevgradle.legacyforge.dsl.MixinExtension +import net.neoforged.moddevgradle.legacyforge.dsl.ObfuscationExtension val mcVersion = ext["mcVersion"] as Int val mcVersionStr = ext["mcVersionStr"] as String @@ -239,13 +240,15 @@ dependencies { } if (mcVersion < 260100) { - val remapJar by tasks.getting(RemapJarTask::class) { + if (projectPlugin.isLoom()) tasks.getting(RemapJarTask::class) { val shadowJar by tasks.getting(ShadowJar::class) dependsOn(shadowJar) if (isForge && mcVersion >= 12105) { atAccessWideners.add("cobblegen.accesswidener") } inputFile.set(shadowJar.archiveFile) + } else if (projectPlugin.isLegacy) project.the().apply { + reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) } } From 063f92771af522cb8563599ff2a82153ec24e11b Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 20:08:57 +0700 Subject: [PATCH 56/92] fix: Legacy should use lexForge not neo --- cobblegen/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index e7ff9942..1b0e51b1 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -132,7 +132,7 @@ inline fun GradlePlugin.configureNeo(configuration: if (projectPlugin.isLoom()) projectPlugin.configureLoom() else if (projectPlugin.isLegacy) projectPlugin.configureNeo { - version = NEO.version(mcVersion) + version = lexForge.version(mcVersion) } else projectPlugin.configureNeo { version = NEO.version(mcVersion) } From 832c11ec1eac8c01cfc3000db48362f2b4a58633 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 29 Jan 2026 20:25:11 +0700 Subject: [PATCH 57/92] docs: Add FIXME note [skip ci] --- cobblegen/build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 1b0e51b1..2d366baa 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -88,6 +88,7 @@ fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit inline fun GradlePlugin.configureNeo(configuration: T.() -> Unit = {}) { project.the() .apply { + // FIXME: AccessWidener to AccessTransformer validateAccessTransformers = true runs { @@ -240,7 +241,7 @@ dependencies { } if (mcVersion < 260100) { - if (projectPlugin.isLoom()) tasks.getting(RemapJarTask::class) { + if (projectPlugin.isLoom()) tasks.named("remapJar") { val shadowJar by tasks.getting(ShadowJar::class) dependsOn(shadowJar) if (isForge && mcVersion >= 12105) { From ac0cbb51e7aee900a961d041874c32df7b5933b1 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 07:22:05 +0700 Subject: [PATCH 58/92] chore: AT --- cobblegen/src/main/resources/META-INF/accesstransformer.cfg | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cobblegen/src/main/resources/META-INF/accesstransformer.cfg diff --git a/cobblegen/src/main/resources/META-INF/accesstransformer.cfg b/cobblegen/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 00000000..f0fa284f --- /dev/null +++ b/cobblegen/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1,4 @@ +public net.minecraft.resources.RegistryDataLoader$Loader + +public net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager$Source +public net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager$Source (Ljava/util/function/Function;Ljava/util/function/Supplier;)V From f7ce0760b4dcec472b12a5e56b2cebc0d9e53615 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 08:16:21 +0700 Subject: [PATCH 59/92] fix: Fix shaded jars --- cobblegen/build.gradle.kts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 2d366baa..d069131e 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -241,9 +241,8 @@ dependencies { } if (mcVersion < 260100) { - if (projectPlugin.isLoom()) tasks.named("remapJar") { + if (projectPlugin.isLoom()) tasks.withType { val shadowJar by tasks.getting(ShadowJar::class) - dependsOn(shadowJar) if (isForge && mcVersion >= 12105) { atAccessWideners.add("cobblegen.accesswidener") } @@ -253,7 +252,10 @@ if (mcVersion < 260100) { } } -val jar by tasks.getting(Jar::class) { +tasks.withType { + if (mcVersion >= 260100 || !projectPlugin.isLoom()) { + from(zipTree(tasks.named("shadowJar").map { it.archiveFile })) {} + } manifest.attributes(mapOf( "MixinConfigs" to "cobblegen.mixins.json", )) From 5931d00aa0abfd824c3120d19e50ee2ab108f6a3 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 08:46:46 +0700 Subject: [PATCH 60/92] fix: Different approach to fix shaded jars --- cobblegen/build.gradle.kts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index d069131e..2f525946 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -8,6 +8,7 @@ import net.neoforged.moddevgradle.dsl.NeoForgeExtension import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension import net.neoforged.moddevgradle.legacyforge.dsl.MixinExtension import net.neoforged.moddevgradle.legacyforge.dsl.ObfuscationExtension +import net.neoforged.moddevgradle.tasks.JarJar val mcVersion = ext["mcVersion"] as Int val mcVersionStr = ext["mcVersionStr"] as String @@ -240,6 +241,13 @@ dependencies { } } +tasks.withType { + archiveClassifier = "dev" + manifest.attributes(mapOf( + "MixinConfigs" to "cobblegen.mixins.json", + )) +} + if (mcVersion < 260100) { if (projectPlugin.isLoom()) tasks.withType { val shadowJar by tasks.getting(ShadowJar::class) @@ -252,13 +260,20 @@ if (mcVersion < 260100) { } } -tasks.withType { +val productionJar by tasks.register("productionJar") { + archiveClassifier = "" + archiveExtension = "jar" + destinationDirectory = layout.buildDirectory.dir("libs") if (mcVersion >= 260100 || !projectPlugin.isLoom()) { - from(zipTree(tasks.named("shadowJar").map { it.archiveFile })) {} + from(zipTree(tasks.named("shadowJar").flatMap { it.archiveFile })) + } else { + from(zipTree(tasks.named("remapJar").flatMap { it.archiveFile })) } - manifest.attributes(mapOf( - "MixinConfigs" to "cobblegen.mixins.json", - )) + if (!projectPlugin.isLoom()) from(tasks.named("jarJar")) +} + +tasks.assemble { + dependsOn(productionJar) } //val deleteResources by tasks.creating(Delete::class) { From 64c9d130a0e11b05bbb4ae5afadceb7f90666102 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 08:57:01 +0700 Subject: [PATCH 61/92] fix: Don't do productionJar on legacy loom --- cobblegen/build.gradle.kts | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 2f525946..71bd5491 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -242,7 +242,6 @@ dependencies { } tasks.withType { - archiveClassifier = "dev" manifest.attributes(mapOf( "MixinConfigs" to "cobblegen.mixins.json", )) @@ -258,22 +257,22 @@ if (mcVersion < 260100) { } else if (projectPlugin.isLegacy) project.the().apply { reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) } -} +} else { + tasks.withType { + archiveClassifier = "dev" + } -val productionJar by tasks.register("productionJar") { - archiveClassifier = "" - archiveExtension = "jar" - destinationDirectory = layout.buildDirectory.dir("libs") - if (mcVersion >= 260100 || !projectPlugin.isLoom()) { - from(zipTree(tasks.named("shadowJar").flatMap { it.archiveFile })) - } else { - from(zipTree(tasks.named("remapJar").flatMap { it.archiveFile })) + val productionJar by tasks.register("productionJar") { + archiveClassifier = "" + archiveExtension = "jar" + destinationDirectory = layout.buildDirectory.dir("libs") + from(zipTree(tasks.shadowJar.flatMap { it.archiveFile })) + if (!projectPlugin.isLoom()) from(tasks.named("jarJar")) } - if (!projectPlugin.isLoom()) from(tasks.named("jarJar")) -} -tasks.assemble { - dependsOn(productionJar) + tasks.assemble { + dependsOn(productionJar) + } } //val deleteResources by tasks.creating(Delete::class) { From 87e29833c7c905d5ebb000f7982292a063d1e915 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 08:59:50 +0700 Subject: [PATCH 62/92] fix: Explicitly declare depends on jar --- cobblegen/build.gradle.kts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 71bd5491..c03824ba 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -241,7 +241,7 @@ dependencies { } } -tasks.withType { +tasks.jar { manifest.attributes(mapOf( "MixinConfigs" to "cobblegen.mixins.json", )) @@ -258,11 +258,12 @@ if (mcVersion < 260100) { reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) } } else { - tasks.withType { + tasks.jar { archiveClassifier = "dev" } val productionJar by tasks.register("productionJar") { + dependsOn(tasks.jar) archiveClassifier = "" archiveExtension = "jar" destinationDirectory = layout.buildDirectory.dir("libs") From 2d0df6f3b6423fad9881fb76a834bd4f35c51884 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 09:13:09 +0700 Subject: [PATCH 63/92] fix: REI moment again --- cobblegen/build.gradle.kts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index c03824ba..4f85b120 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -213,7 +213,7 @@ dependencies { // <- REI // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) - if (mcVersion in 12002..12104) { // FIXME: Not sure why it's not included + if ((isFabric && mcVersion in 12002..12104) || (isForge && mcVersion in 11802..12001)) { // FIXME: Not sure why it's not included dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") dep("modCompileOnly", "dev.architectury:architectury:11.1.13") } @@ -257,7 +257,9 @@ if (mcVersion < 260100) { } else if (projectPlugin.isLegacy) project.the().apply { reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) } -} else { +} + +if (mcVersion >= 260100 || !projectPlugin.isLoom()){ tasks.jar { archiveClassifier = "dev" } From 0d878a591606f7dbc9795d18211745fb6f353640 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 09:51:41 +0700 Subject: [PATCH 64/92] fix: Include shaded deps to runtime classpath ArchLoom and MDG aren't so different after all -_- --- build.gradle.kts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 725879fe..6df0480e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -192,8 +192,9 @@ subprojects { configurations.testAnnotationProcessor.get().extendsFrom(this) } - if (isModModule && !isFabric && projectPlugin is GradlePlugin.ArchLoom) { - configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) + if (isModModule && !isFabric) { + val configName = if (projectPlugin.isLoom()) "forgeRuntimeLibrary" else "additionalRuntimeClasspath" + configurations.named(configName).get().extendsFrom(shade) } val loom by lazy { From 0c9f462910fa3b6005b58678ae1d22cbd8d8b5e6 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 10:04:54 +0700 Subject: [PATCH 65/92] fix: Add mixin processor AP --- cobblegen/build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 4f85b120..f1b1289c 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -184,6 +184,9 @@ dependencies { } else { "neoForge"(NEO.versioned(mcVersion)) } + } else if (projectPlugin.isLegacy) { + // needed for legacy forge, for mapping stuff + annotationProcessor("org.spongepowered:mixin:0.8.7:processor") } if (mcVersion > 11605) { From 5f06593dc4f6f5c1d292177974a49359183d2d12 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 10:42:45 +0700 Subject: [PATCH 66/92] fix: Wtf? "Configuration with name 'additionalRuntimeClasspath' not found."?? --- build.gradle.kts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6df0480e..4ba8c112 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -193,8 +193,12 @@ subprojects { } if (isModModule && !isFabric) { - val configName = if (projectPlugin.isLoom()) "forgeRuntimeLibrary" else "additionalRuntimeClasspath" - configurations.named(configName).get().extendsFrom(shade) + if (projectPlugin.isLoom()) configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) + else { + if (mcVersion <= 12108) { + configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) + } + } } val loom by lazy { From ce09c2165462f5ec0b2512e1fadc76da05ad5e90 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 10:46:23 +0700 Subject: [PATCH 67/92] fix: Extend after evaluate --- build.gradle.kts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4ba8c112..3e161b48 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -195,8 +195,10 @@ subprojects { if (isModModule && !isFabric) { if (projectPlugin.isLoom()) configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) else { - if (mcVersion <= 12108) { - configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) + afterEvaluate { + if (mcVersion <= 12108) { + configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) + } } } } From fa8b8545bf63c3380a6f5a93a4ceef802dba1ea4 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 11:14:52 +0700 Subject: [PATCH 68/92] fix: Also add internal lib to additional runtime classpath --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index 3e161b48..7cbf8c38 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -198,6 +198,7 @@ subprojects { afterEvaluate { if (mcVersion <= 12108) { configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) + configurations.named("additionalRuntimeClasspath").get().extendsFrom(shadeInternal) } } } From e03a09e8f4c569f1765d319e734050014d590bc2 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 11:27:26 +0700 Subject: [PATCH 69/92] fix: Extends from compile internal instead --- build.gradle.kts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7cbf8c38..903323eb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -184,6 +184,11 @@ subprojects { if (isModModule && projectPlugin is GradlePlugin.ArchLoom) { configurations["development$loaderProd"].extendsFrom(this) } + afterEvaluate { + if (isModModule && mcVersion <= 12108 && !projectPlugin.isLoom()) { + configurations.named("additionalRuntimeClasspath").get().extendsFrom(this@creating) + } + } } val manifoldCompile: Configuration by configurations.creating { @@ -198,7 +203,6 @@ subprojects { afterEvaluate { if (mcVersion <= 12108) { configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) - configurations.named("additionalRuntimeClasspath").get().extendsFrom(shadeInternal) } } } From e564820e0f5457b45e92b36c501ba1855692b836 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 11:42:02 +0700 Subject: [PATCH 70/92] fix: Finalize jar with reobfJar --- cobblegen/build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index f1b1289c..a7abe5a6 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -258,6 +258,9 @@ if (mcVersion < 260100) { } inputFile.set(shadowJar.archiveFile) } else if (projectPlugin.isLegacy) project.the().apply { + tasks.jar { + finalizedBy(tasks.named("reobfJar")) + } reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) } } From 8d27343a5c96b322b4584cc41d9250c1a2ca805a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 12:08:52 +0700 Subject: [PATCH 71/92] refactor: Replace VanillaGradle with Neo's MDG in Vanilla-mode --- .../src/main/kotlin/dependencies/NeoForge.kt | 21 ++++++++++++ mclib/build.gradle.kts | 32 +++++++++++++++---- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index 16388cff..af62eb41 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -22,3 +22,24 @@ val NEO = Dependency( "${mc}.${version}" }, ) + +val NEOFORM = Dependency( + group = "net.neoforged", + name = "neoforge", + version = { mcVersion -> + val version = when (mcVersion) { + in 12002..12003 -> "20241215.201144" + 12004 -> "20240627.114801" + in 12005..12006 -> "20240627.102356" + in 12100..12101 -> "20240808.144430" + in 12102..12104 -> "20241023.131943" + in 12105..12110 -> "20250325.162830" + 12111 -> "20251209.172050" + 260100 -> "snapshot-5-1" + else -> throw IllegalStateException("Version $mcVersion is not yet supported!") + } + val mc = versionStr(mcVersion, false) + + "${mc}-${version}" + } +) diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 22f8cc04..36dd2241 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -1,11 +1,31 @@ +import dependencies.NEOFORM +import net.neoforged.moddevgradle.dsl.ModDevExtension +import net.neoforged.moddevgradle.dsl.NeoForgeExtension +import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension import dependencies.minecraft as MC -plugins { - id("org.spongepowered.gradle.vanilla") +val mcVersion = ext["mcVersion"] as Int +val projectPlugin = extra["projectPlugin"] as GradlePlugin +if (projectPlugin.isLegacy) { + apply(GradlePlugin.LegacyMDG.id) +} else { + apply(GradlePlugin.MDG.id) } -minecraft { - version(MC.version(project.ext["mcVersion"] as Int)) +inline fun GradlePlugin.configure(configuration: T.() -> Unit = {}) { + project.the() + .apply {} + .configuration() +} + +if (projectPlugin.isLegacy) { + projectPlugin.configure { + mcpVersion = MC.version(mcVersion) + } +} else { + projectPlugin.configure { + neoFormVersion = NEOFORM.version(mcVersion) + } } repositories { @@ -13,7 +33,7 @@ repositories { } dependencies { - compileOnly("org.spongepowered:mixin:0.8.5") + compileOnly("org.spongepowered:mixin:0.8.7") } publishing { @@ -24,9 +44,7 @@ publishing { } } - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. repositories { - // Add repositories to publish to here. } } From 6fe3d39b92a272b8c2b1ee6403dd28ab2465714e Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 12:39:41 +0700 Subject: [PATCH 72/92] fix: Apply plugin not file --- mclib/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 36dd2241..11d2921d 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -7,9 +7,9 @@ import dependencies.minecraft as MC val mcVersion = ext["mcVersion"] as Int val projectPlugin = extra["projectPlugin"] as GradlePlugin if (projectPlugin.isLegacy) { - apply(GradlePlugin.LegacyMDG.id) + apply(plugin = GradlePlugin.LegacyMDG.id) } else { - apply(GradlePlugin.MDG.id) + apply(plugin = GradlePlugin.MDG.id) } inline fun GradlePlugin.configure(configuration: T.() -> Unit = {}) { From dc6a1e116af1f2f370c5eb0bd46a70237abfe662 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 12:51:27 +0700 Subject: [PATCH 73/92] revert: "Replace VanillaGradle with Neo's MDG in Vanilla-mode" This reverts commit 8d27343a5c96b322b4584cc41d9250c1a2ca805a. This reverts commit 6fe3d39b92a272b8c2b1ee6403dd28ab2465714e. --- .../src/main/kotlin/dependencies/NeoForge.kt | 21 ------------ mclib/build.gradle.kts | 32 ++++--------------- 2 files changed, 7 insertions(+), 46 deletions(-) diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index af62eb41..16388cff 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -22,24 +22,3 @@ val NEO = Dependency( "${mc}.${version}" }, ) - -val NEOFORM = Dependency( - group = "net.neoforged", - name = "neoforge", - version = { mcVersion -> - val version = when (mcVersion) { - in 12002..12003 -> "20241215.201144" - 12004 -> "20240627.114801" - in 12005..12006 -> "20240627.102356" - in 12100..12101 -> "20240808.144430" - in 12102..12104 -> "20241023.131943" - in 12105..12110 -> "20250325.162830" - 12111 -> "20251209.172050" - 260100 -> "snapshot-5-1" - else -> throw IllegalStateException("Version $mcVersion is not yet supported!") - } - val mc = versionStr(mcVersion, false) - - "${mc}-${version}" - } -) diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 11d2921d..22f8cc04 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -1,31 +1,11 @@ -import dependencies.NEOFORM -import net.neoforged.moddevgradle.dsl.ModDevExtension -import net.neoforged.moddevgradle.dsl.NeoForgeExtension -import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension import dependencies.minecraft as MC -val mcVersion = ext["mcVersion"] as Int -val projectPlugin = extra["projectPlugin"] as GradlePlugin -if (projectPlugin.isLegacy) { - apply(plugin = GradlePlugin.LegacyMDG.id) -} else { - apply(plugin = GradlePlugin.MDG.id) +plugins { + id("org.spongepowered.gradle.vanilla") } -inline fun GradlePlugin.configure(configuration: T.() -> Unit = {}) { - project.the() - .apply {} - .configuration() -} - -if (projectPlugin.isLegacy) { - projectPlugin.configure { - mcpVersion = MC.version(mcVersion) - } -} else { - projectPlugin.configure { - neoFormVersion = NEOFORM.version(mcVersion) - } +minecraft { + version(MC.version(project.ext["mcVersion"] as Int)) } repositories { @@ -33,7 +13,7 @@ repositories { } dependencies { - compileOnly("org.spongepowered:mixin:0.8.7") + compileOnly("org.spongepowered:mixin:0.8.5") } publishing { @@ -44,7 +24,9 @@ publishing { } } + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. repositories { + // Add repositories to publish to here. } } From d348b17033c7ee8f28a619a031d97c3260f19e3b Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 16:42:21 +0700 Subject: [PATCH 74/92] ci: Disable gradle gametest for Forge 1.18.2-1.20.1 SRG is being stupid again, I wish they added Runtime Mojmap long ago, I blame lex. --- .github/workflows/build.yml | 2 +- cobblegen/build.gradle.kts | 2 +- gradle.properties | 6 +-- mclib/build.gradle.kts | 6 +-- .../minecraft/world/level/Level/LevelExt.java | 5 +- .../level/LevelAccessor/LevelAccessorExt.java | 1 + versions.json | 50 +++++++++---------- 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index acc10d57..150f1cd2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -131,7 +131,7 @@ jobs: retention-days: 3 - name: GameTest with Gradle - if: github.event.inputs.bypass-test != 'true' && matrix.mc != '1.16.5' + if: github.event.inputs.bypass-test != 'true' && matrix.gradleGameTest run: | echo "# GameTest results" >> $GITHUB_STEP_SUMMARY; echo "" >> $GITHUB_STEP_SUMMARY; diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index a7abe5a6..a13875b4 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -90,7 +90,7 @@ inline fun GradlePlugin.configureNeo(configuration: project.the() .apply { // FIXME: AccessWidener to AccessTransformer - validateAccessTransformers = true + validateAccessTransformers = mcVersion >= 12105 runs { create("client") { diff --git a/gradle.properties b/gradle.properties index 50f1e726..a5afb550 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,15 +19,15 @@ recipe_viewer=none # Dependencies jankson_version=1.2.3 -manifold_version=2025.1.28 +manifold_version=2025.1.31 # Version Specific Dependencies create_version_1_18_2=0.5.1-f-build.1333+mc1.18.2 port_lib_version_1_18_2=1.2.869-beta+1.18.2 # Default MC version and loader name for IDEs, will be overwritten by gradle build argument -PmcVer or -PloaderName -mcVer=1.21.11 -null2264.platform=fabric +mcVer=1.18.2 +null2264.platform=forge forge.enableGameTest=true neoforge.enableGameTest=true null2264.cobblegen.gametest=true diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index 22f8cc04..d359bac6 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -31,7 +31,7 @@ publishing { } tasks.jar { - manifest { - attributes["Contains-Sources"] = "java,class" - } + manifest.attributes(mapOf( + "Contains-Sources" to "java,class", + )) } diff --git a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java b/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java index 5dd43634..fe893c53 100644 --- a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java +++ b/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java @@ -1,10 +1,11 @@ package io.github.null2264.cobblegen.extensions.net.minecraft.world.level.Level; -import manifold.ext.rt.api.Extension; +#if MC>12101 import manifold.ext.rt.api.This; import net.minecraft.world.level.Level; +#endif -@Extension +@manifold.ext.rt.api.Extension public final class LevelExt { #if MC>12101 public static int getMinBuildHeight(@This Level thiz) { diff --git a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java b/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java index c92606b5..01de039a 100644 --- a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java +++ b/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java @@ -6,6 +6,7 @@ @manifold.ext.rt.api.Extension public final class LevelAccessorExt { + public static RegistryAccess registryAccessCompat(@manifold.ext.rt.api.This LevelAccessor thiz) { RegistryAccess access = null; // Pre-runtime-mojmap forge pain (which introduced on NeoForge around MC 1.20.2 and Forge around 1.20.6, be it partially) diff --git a/versions.json b/versions.json index 3cd4874f..207a4bec 100644 --- a/versions.json +++ b/versions.json @@ -1,40 +1,40 @@ { "include": [ - { "mc": "1.16.5", "loader": "fabric", "java": "8", "testVersions": ["1.16.5"] }, - { "mc": "1.16.5", "loader": "forge", "java": "8", "testVersions": ["1.16.5"] }, + { "mc": "1.16.5", "loader": "fabric", "java": "8", "gradleGameTest": false, "testVersions": ["1.16.5"] }, + { "mc": "1.16.5", "loader": "forge", "java": "8", "gradleGameTest": false, "testVersions": ["1.16.5"] }, - { "mc": "1.18.2", "loader": "fabric", "java": "17", "testVersions": ["1.18.2"] }, - { "mc": "1.18.2", "loader": "forge", "java": "17", "testVersions": ["1.18.2"] }, + { "mc": "1.18.2", "loader": "fabric", "java": "17", "gradleGameTest": true, "testVersions": ["1.18.2"] }, + { "mc": "1.18.2", "loader": "forge", "java": "17", "gradleGameTest": false, "testVersions": ["1.18.2"] }, - { "mc": "1.19.2", "loader": "fabric", "java": "17", "testVersions": ["1.19", "1.19.1", "1.19.2"] }, - { "mc": "1.19.2", "loader": "forge", "java": "17", "testVersions": ["1.19", "1.19.1", "1.19.2"] }, + { "mc": "1.19.2", "loader": "fabric", "java": "17", "gradleGameTest": true, "testVersions": ["1.19", "1.19.1", "1.19.2"] }, + { "mc": "1.19.2", "loader": "forge", "java": "17", "gradleGameTest": false, "testVersions": ["1.19", "1.19.1", "1.19.2"] }, - { "mc": "1.19.4", "loader": "fabric", "java": "17", "testVersions": ["1.19.3", "1.19.4"] }, - { "mc": "1.19.4", "loader": "forge", "java": "17", "testVersions": ["1.19.3", "1.19.4"] }, + { "mc": "1.19.4", "loader": "fabric", "java": "17", "gradleGameTest": true, "testVersions": ["1.19.3", "1.19.4"] }, + { "mc": "1.19.4", "loader": "forge", "java": "17", "gradleGameTest": false, "testVersions": ["1.19.3", "1.19.4"] }, - { "mc": "1.20.1", "loader": "fabric", "java": "17", "testVersions": ["1.20.1"] }, - { "mc": "1.20.1", "loader": "forge", "java": "17", "testVersions": ["1.20.1"] }, + { "mc": "1.20.1", "loader": "fabric", "java": "17", "gradleGameTest": true, "testVersions": ["1.20.1"] }, + { "mc": "1.20.1", "loader": "forge", "java": "17", "gradleGameTest": false, "testVersions": ["1.20.1"] }, - { "mc": "1.20.2", "loader": "fabric", "java": "17", "testVersions": ["1.20.2", "1.20.3", "1.20.4"] }, - { "mc": "1.20.2", "loader": "neoforge", "java": "17", "testVersions": ["1.20.2", "1.20.3"] }, - { "mc": "1.20.4", "loader": "neoforge", "java": "17", "testVersions": ["1.20.4"] }, + { "mc": "1.20.2", "loader": "fabric", "java": "17", "gradleGameTest": true, "testVersions": ["1.20.2", "1.20.3", "1.20.4"] }, + { "mc": "1.20.2", "loader": "neoforge", "java": "17", "gradleGameTest": true, "testVersions": ["1.20.2", "1.20.3"] }, + { "mc": "1.20.4", "loader": "neoforge", "java": "17", "gradleGameTest": true, "testVersions": ["1.20.4"] }, - { "mc": "1.20.6", "loader": "fabric", "java": "17", "testVersions": ["1.20.6"] }, - { "mc": "1.20.6", "loader": "neoforge", "java": "17", "testVersions": ["1.20.6"] }, + { "mc": "1.20.6", "loader": "fabric", "java": "17", "gradleGameTest": true, "testVersions": ["1.20.6"] }, + { "mc": "1.20.6", "loader": "neoforge", "java": "17", "gradleGameTest": true, "testVersions": ["1.20.6"] }, - { "mc": "1.21.1", "loader": "fabric", "java": "21", "testVersions": ["1.21", "1.21.1"] }, - { "mc": "1.21.1", "loader": "neoforge", "java": "21", "testVersions": ["1.21", "1.21.1"] }, + { "mc": "1.21.1", "loader": "fabric", "java": "21", "gradleGameTest": true, "testVersions": ["1.21", "1.21.1"] }, + { "mc": "1.21.1", "loader": "neoforge", "java": "21", "gradleGameTest": true, "testVersions": ["1.21", "1.21.1"] }, - { "mc": "1.21.3", "loader": "fabric", "java": "21", "testVersions": ["1.21.3", "1.21.4"] }, - { "mc": "1.21.3", "loader": "neoforge", "java": "21", "testVersions": ["1.21.3", "1.21.4"] }, + { "mc": "1.21.3", "loader": "fabric", "java": "21", "gradleGameTest": true, "testVersions": ["1.21.3", "1.21.4"] }, + { "mc": "1.21.3", "loader": "neoforge", "java": "21", "gradleGameTest": true, "testVersions": ["1.21.3", "1.21.4"] }, - { "mc": "1.21.5", "loader": "fabric", "java": "21", "testVersions": ["1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10"] }, - { "mc": "1.21.5", "loader": "neoforge", "java": "21", "testVersions": ["1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10"] }, + { "mc": "1.21.5", "loader": "fabric", "java": "21", "gradleGameTest": true, "testVersions": ["1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10"] }, + { "mc": "1.21.5", "loader": "neoforge", "java": "21", "gradleGameTest": true, "testVersions": ["1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10"] }, - { "mc": "1.21.11", "loader": "fabric", "java": "21", "testVersions": ["1.21.11"] }, - { "mc": "1.21.11", "loader": "neoforge", "java": "21", "testVersions": ["1.21.11"] }, + { "mc": "1.21.11", "loader": "fabric", "java": "21", "gradleGameTest": true, "testVersions": ["1.21.11"] }, + { "mc": "1.21.11", "loader": "neoforge", "java": "21", "gradleGameTest": true, "testVersions": ["1.21.11"] }, - { "mc": "26.1", "loader": "fabric", "java": "25", "testVersions": ["26.1"] }, - { "mc": "26.1", "loader": "neoforge", "java": "25", "testVersions": ["26.1"] } + { "mc": "26.1", "loader": "fabric", "java": "25", "gradleGameTest": true, "testVersions": ["26.1"] }, + { "mc": "26.1", "loader": "neoforge", "java": "25", "gradleGameTest": true, "testVersions": ["26.1"] } ] } From e36ce8244205e588e63427538f64b6b8753185f7 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 30 Jan 2026 16:53:32 +0700 Subject: [PATCH 75/92] chore: Set gradle.properties value back to 26.1 fabric --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a5afb550..fcf385ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,8 +26,8 @@ create_version_1_18_2=0.5.1-f-build.1333+mc1.18.2 port_lib_version_1_18_2=1.2.869-beta+1.18.2 # Default MC version and loader name for IDEs, will be overwritten by gradle build argument -PmcVer or -PloaderName -mcVer=1.18.2 -null2264.platform=forge +mcVer=26.1 +null2264.platform=fabric forge.enableGameTest=true neoforge.enableGameTest=true null2264.cobblegen.gametest=true From b246ae4efdc0cd116f63cfc24521fffbcf9448f7 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 09:16:32 +0700 Subject: [PATCH 76/92] refactor: CGVer to start cleaning up gradle setup --- build.gradle.kts | 40 ++++++------ buildSrc/src/main/kotlin/CGVer.kt | 61 +++++++++++++++++++ .../src/main/kotlin/ProcessModMetadata.kt | 30 ++++----- buildSrc/src/main/kotlin/VersionRange.kt | 4 +- .../src/main/kotlin/dependencies/Create.kt | 2 +- .../main/kotlin/dependencies/Dependencies.kt | 6 +- .../src/main/kotlin/dependencies/FabricAPI.kt | 6 +- .../src/main/kotlin/dependencies/LexForge.kt | 4 +- .../src/main/kotlin/dependencies/Minecraft.kt | 4 +- .../src/main/kotlin/dependencies/NeoForge.kt | 7 ++- .../main/kotlin/dependencies/RecipeViewer.kt | 32 +++++----- cobblegen/build.gradle.kts | 43 +++++++------ mclib/build.gradle.kts | 2 +- stubs/build.gradle.kts | 2 +- 14 files changed, 153 insertions(+), 90 deletions(-) create mode 100644 buildSrc/src/main/kotlin/CGVer.kt diff --git a/build.gradle.kts b/build.gradle.kts index 903323eb..aa262e70 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,11 +24,7 @@ val isForge = loaderName.endsWith("forge") val isNeo = loaderName.endsWith("neoforge") val isFabric = loaderName.endsWith("fabric") val mcVersionStr = project.properties["mcVer"] as? String ?: "" -val (major, minor, patch) = mcVersionStr - .split(".") - .toMutableList() - .apply { while (this.size < 3) this.add("") } -val mcVersion: Int = "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt() +val mcVersion = CGVer.fromString(mcVersionStr) val versionRange = supportedVersionRange(mcVersion, loaderName) /** @@ -36,18 +32,18 @@ val versionRange = supportedVersionRange(mcVersion, loaderName) */ val projectPlugin = when { // LegacyMDG only support 1.17 up to 1.20.1 - mcVersion <= 11605 -> GradlePlugin.ArchLoom + mcVersion.code <= 11605 -> GradlePlugin.ArchLoom isNeo -> when { - mcVersion <= 12001 -> GradlePlugin.LegacyMDG + mcVersion.code <= 12001 -> GradlePlugin.LegacyMDG // 1.20.2+ is in some kind of limbo for whatever reason, not supported by MDG and not supported by LegacyMDG. - mcVersion in 12002..12006 -> GradlePlugin.ArchLoom + mcVersion.code in 12002..12006 -> GradlePlugin.ArchLoom else -> GradlePlugin.MDG } isForge -> { - assert(mcVersion <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } + assert(mcVersion.code <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } GradlePlugin.LegacyMDG } - isFabric -> if (mcVersion <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom + isFabric -> if (mcVersion.code <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom else -> throw IllegalStateException() } @@ -185,7 +181,7 @@ subprojects { configurations["development$loaderProd"].extendsFrom(this) } afterEvaluate { - if (isModModule && mcVersion <= 12108 && !projectPlugin.isLoom()) { + if (isModModule && mcVersion.code <= 12108 && !projectPlugin.isLoom()) { configurations.named("additionalRuntimeClasspath").get().extendsFrom(this@creating) } } @@ -201,7 +197,7 @@ subprojects { if (projectPlugin.isLoom()) configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) else { afterEvaluate { - if (mcVersion <= 12108) { + if (mcVersion.code <= 12108) { configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) } } @@ -243,7 +239,7 @@ subprojects { isTransitive = false } - if (mcVersion <= 11605) { + if (mcVersion.code <= 11605) { // slf4j is not included by MC in 1.16.5 shade("org.slf4j:slf4j-api:1.7.36") shade("org.apache.logging.log4j:log4j-slf4j-impl:2.8.1") @@ -254,7 +250,7 @@ subprojects { val shadowJar by tasks.getting(ShadowJar::class) { isZip64 = true relocate("blue.endless.jankson", "io.github.null2264.shadowed.jankson") - if (mcVersion <= 11605) { + if (mcVersion.code <= 11605) { relocate("org.slf4j", "io.github.null2264.shadowed.slf4j") relocate("org.apache.logging", "io.github.null2264.shadowed.log4j") } @@ -265,7 +261,7 @@ subprojects { exclude("META-INF/neoforge.mods.toml") } else if (isForge) { exclude("fabric.mod.json") - exclude(if (isNeo && mcVersion >= 12006) "META-INF/mods.toml" else "META-INF/neoforge.mods.toml") + exclude(if (isNeo && mcVersion.code >= 12006) "META-INF/mods.toml" else "META-INF/neoforge.mods.toml") } exclude("architectury.common.json") @@ -293,7 +289,7 @@ subprojects { if (isFabric) { "fabric.mod.json" } else { - if (isNeo && mcVersion >= 12006) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml" + if (isNeo && mcVersion.code >= 12006) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml" } filesMatching(metadataFilename) { @@ -307,8 +303,8 @@ subprojects { doLast { // For some reason Mojang rename the structure directory on MC 1.21 to singular form - val structureDirName = if (mcVersion >= 12100) "structure" else "structures" - if (isFabric || mcVersion >= 12105) { + val structureDirName = if (mcVersion.code >= 12100) "structure" else "structures" + if (isFabric || mcVersion.code >= 12105) { project.file("build/resources/main/data/cobblegen/gametest/${structureDirName}/").mkdirs() project.file("build/resources/main/data/cobblegen/gametest/${structureDirName}/empty.snbt") .writeStructureAsSnbt(generateStructure(false)) @@ -328,7 +324,7 @@ subprojects { } val targetJavaVersion = if (!isApi) { - when (mcVersion) { + when (mcVersion.code) { in 11200..11605 -> 8 in 11700..11701 -> 16 in 11800..12004 -> 17 @@ -395,7 +391,7 @@ publishMods { append(modVersion) append("-") append(rootProject.properties["version_stage"]) - if (mcVersion <= 11605) append(" (LITE)") + if (mcVersion.code <= 11605) append(" (LITE)") } ) changelog.set(System.getenv("CHANGELOG") ?: "Please visit our [releases](https://github.com/null2264/CobbleGen/releases) for a changelog") @@ -404,9 +400,9 @@ publishMods { modLoaders.add("fabric") modLoaders.add("quilt") } else { - if (mcVersion <= 12002 && !isNeo) // No more LexForge, LexForge is too buggy + if (mcVersion.code <= 12002 && !isNeo) // No more LexForge, LexForge is too buggy modLoaders.add("forge") - if (mcVersion == 12001 || isNeo) + if (mcVersion.code == 12001 || isNeo) modLoaders.add("neoforge") } type = when(rootProject.properties["version_stage"]) { diff --git a/buildSrc/src/main/kotlin/CGVer.kt b/buildSrc/src/main/kotlin/CGVer.kt new file mode 100644 index 00000000..e33c9478 --- /dev/null +++ b/buildSrc/src/main/kotlin/CGVer.kt @@ -0,0 +1,61 @@ +data class CGVer( + val code: Int, + var alwaysShowHotfix: Boolean = false, +) { + internal fun legacyVersionStr(versionCode: Int): String { + val versionCodeStr = versionCode.toString() + val major = versionCodeStr.getOrNull(0)?.toString() ?: "0" + val minor = versionCodeStr + .substring(1, 3) + .padStart(2, '0') + .trimStart('0') + val patch = versionCodeStr + .substring(3) + .padEnd(1, '0').trimStart('0') + + if (patch.isEmpty()) return "$major.$minor" + return "$major.$minor.$patch" + } + + val isWildcard: Boolean + get() = code < 0 + + val string: String + get() { + assert(!isWildcard) { "Can't transform a wildcard to string format!" } + + val versionCodeStr = code.toString() + if (versionCodeStr.length == 5) return legacyVersionStr(code) + + val year = versionCodeStr.substring(0, 2) + val release = versionCodeStr + .substring(2, 4) + .trimStart('0') + .let { if (it == "") "0" else it } + val hotfix = versionCodeStr + .substring(4) + .trimStart('0') + .let { if (it == "" && alwaysShowHotfix) "0" else it } + + return if (hotfix != "") "$year.$release.$hotfix" else "$year.$release" + } + + override fun toString(): String { + return string + } + + companion object { + fun fromString(string: String, alwaysShowHotfix: Boolean = false): CGVer { + val (major, minor, patch) = string + .split(".") + .toMutableList() + .apply { while (this.size < 3) this.add("") } + return CGVer( + "${major}${minor.padStart(2, '0')}${patch.padStart(2, '0')}".toInt(), + alwaysShowHotfix, + ) + } + + fun wildcard() = CGVer(-1) + } +} diff --git a/buildSrc/src/main/kotlin/ProcessModMetadata.kt b/buildSrc/src/main/kotlin/ProcessModMetadata.kt index f18f92f0..9190f28a 100644 --- a/buildSrc/src/main/kotlin/ProcessModMetadata.kt +++ b/buildSrc/src/main/kotlin/ProcessModMetadata.kt @@ -7,7 +7,7 @@ import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive fun File.processModsToml( - mcVersion: Int, + mcVersion: CGVer, /** * Possible values: * - 0 -> Not Forge @@ -18,7 +18,7 @@ fun File.processModsToml( ) { val modsTomlContent = readText(Charsets.UTF_8).let { when { - mcVersion == 12001 -> it.replace("#==", "") + mcVersion.code == 12001 -> it.replace("#==", "") forge == 2 -> it.replace("#<<", "") forge == 1 -> it.replace("#>>", "") else -> it @@ -27,12 +27,12 @@ fun File.processModsToml( writeText(modsTomlContent) } -fun File.processMixinsJson(mcVersion: Int, isFabric: Boolean) { +fun File.processMixinsJson(mcVersion: CGVer, isFabric: Boolean) { val both = buildList { - if (mcVersion >= 12005) addJson("network.packet.CustomPacketPayloadMixin") + if (mcVersion.code >= 12005) addJson("network.packet.CustomPacketPayloadMixin") addJson("CommandsMixin") addJson("MinecraftServerMixin") - if (mcVersion > 11605) { + if (mcVersion.code > 11605) { addJson("create.CreateFluidReactionsMixin\$OFive") addJson("create.CreateFluidReactionsMixin\$PatchE") if (isFabric) addJson("create.CreateFluidReactionsMixin\$PatchF") @@ -40,27 +40,27 @@ fun File.processMixinsJson(mcVersion: Int, isFabric: Boolean) { addJson("fluid.FlowingFluidEventMixin") addJson("fluid.FluidEventMixin") addJson("fluid.LavaEventMixin") - if (mcVersion >= 12105) { + if (mcVersion.code >= 12105) { addJson("gametest.RegistryDataLoaderMixin\$GameTest") addJson("gametest.StructureTemplateManagerMixin\$GameTest") } } val client = buildList { - if (mcVersion < 12005) addJson("network.packet.ClientboundCustomPayloadPacketMixin") + if (mcVersion.code < 12005) addJson("network.packet.ClientboundCustomPayloadPacketMixin") addJson("network.ClientCommonPacketListenerMixin") addJson("network.ConnectionMixin") } val server = buildList { addJson("network.PlayerManagerMixin") - if (mcVersion < 12002) addJson("network.ServerboundCustomPayloadPacketAccessor") + if (mcVersion.code < 12002) addJson("network.ServerboundCustomPayloadPacketAccessor") else addJson("network.ServerConfigurationPacketListenerMixin") - if (mcVersion < 12005) addJson("network.packet.ServerboundCustomPayloadPacketMixin") + if (mcVersion.code < 12005) addJson("network.packet.ServerboundCustomPayloadPacketMixin") addJson("network.ServerCommonPacketListenerMixin") - if (!isFabric && mcVersion >= 12004) addJson("network.loader.neoforge.NetworkRegistryMixin") + if (!isFabric && mcVersion.code >= 12004) addJson("network.loader.neoforge.NetworkRegistryMixin") } val mixinsJson = JsonObject( lenientJson.decodeFromString(readText(Charsets.UTF_8)).toMutableMap().apply { - set("compatibilityLevel", JsonPrimitive(if (mcVersion <= 11605) "JAVA_8" else "JAVA_17")) + set("compatibilityLevel", JsonPrimitive(if (mcVersion.code <= 11605) "JAVA_8" else "JAVA_17")) set("mixins", JsonArray(both)) set("client", JsonArray(client)) set("server", JsonArray(server)) @@ -69,13 +69,13 @@ fun File.processMixinsJson(mcVersion: Int, isFabric: Boolean) { writeText(prettyJson.encodeToString(JsonObject.serializer(), mixinsJson)) } -fun File.processFabricModJson(mcVersion: Int) { +fun File.processFabricModJson(mcVersion: CGVer) { val jsonObject = JsonObject( lenientJson.decodeFromString(readText(Charsets.UTF_8)).toMutableMap().apply { (get("entrypoints") as? JsonObject)?.toMutableMap()?.apply { - if (mcVersion > 11605) { + if (mcVersion.code > 11605) { set("jei_mod_plugin", JsonArray(listOf(JsonPrimitive("io.github.null2264.cobblegen.integration.viewer.jei.CGJEIPlugin")))) - if (mcVersion < 12111) { + if (mcVersion.code < 12111) { // FIXME: Enable REI integration for 1.21.11 when REI is updated // REF: https://github.com/shedaniel/RoughlyEnoughItems/pull/1989 set("rei_client", JsonArray(listOf(JsonPrimitive("io.github.null2264.cobblegen.integration.viewer.rei.CGREIPlugin")))) @@ -87,7 +87,7 @@ fun File.processFabricModJson(mcVersion: Int) { "cobblegen_plugin", JsonArray(buildList { addJson("io.github.null2264.cobblegen.integration.BuiltInPlugin") - if (mcVersion > 11605) addJson("io.github.null2264.cobblegen.integration.CreatePlugin") + if (mcVersion.code > 11605) addJson("io.github.null2264.cobblegen.integration.CreatePlugin") }), ) }?.let { diff --git a/buildSrc/src/main/kotlin/VersionRange.kt b/buildSrc/src/main/kotlin/VersionRange.kt index 1106d79a..cf948fa2 100644 --- a/buildSrc/src/main/kotlin/VersionRange.kt +++ b/buildSrc/src/main/kotlin/VersionRange.kt @@ -59,8 +59,8 @@ data class VersionRange( } } -fun supportedVersionRange(mcVersion: Int, loader: String): VersionRange { - return when (mcVersion) { +fun supportedVersionRange(mcVersion: CGVer, loader: String): VersionRange { + return when (mcVersion.code) { 11605 -> VersionRange("1.16.5", "1.16.5") 11802 -> VersionRange("1.18.2", "1.18.2") in 11900..11902 -> VersionRange("1.18.x", "1.19.2") diff --git a/buildSrc/src/main/kotlin/dependencies/Create.kt b/buildSrc/src/main/kotlin/dependencies/Create.kt index 8401b13e..d20879b0 100644 --- a/buildSrc/src/main/kotlin/dependencies/Create.kt +++ b/buildSrc/src/main/kotlin/dependencies/Create.kt @@ -4,7 +4,7 @@ fun createMod(isNeo: Boolean) = Dependency( group = "com.simibubi.create", // Create finally support Neo on 1.21.1 name = "create" + (if (!isNeo) "-1.18.2" else "-1.21.1"), - version = { mcVersion -> + version = { _ -> val version = if (!isNeo) "0.5.1.e-318" else "6.0.4-59" return@Dependency "$version:slim" }, diff --git a/buildSrc/src/main/kotlin/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/dependencies/Dependencies.kt index ac8ee8bb..ab87c6f9 100644 --- a/buildSrc/src/main/kotlin/dependencies/Dependencies.kt +++ b/buildSrc/src/main/kotlin/dependencies/Dependencies.kt @@ -1,11 +1,13 @@ package dependencies +import CGVer + data class Dependency( private val group: String, private val name: String, - val version: (Int) -> String, + val version: (CGVer) -> String, ) { - fun versioned(mcVersion: Int): String = "${group}:${name}:${version(mcVersion)}" + fun versioned(mcVersion: CGVer): String = "${group}:${name}:${version(mcVersion)}" } fun legacyVersionStr(versionCode: Int): String { diff --git a/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt b/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt index 07fb5c42..fbf190f1 100644 --- a/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt +++ b/buildSrc/src/main/kotlin/dependencies/FabricAPI.kt @@ -4,7 +4,7 @@ val fapi = Dependency( group = "net.fabricmc.fabric-api", name = "fabric-api", version = { mcVersion -> - when (mcVersion) { + when (mcVersion.code) { 11605 -> "0.42.0+1.16" 11802 -> "0.76.0+1.18.2" in 11900..11902 -> "0.76.0+1.19.2" @@ -26,7 +26,7 @@ val fapiGameTest = Dependency( group = "net.fabricmc.fabric-api", name = "fabric-gametest-api-v1", version = { mcVersion -> - when (mcVersion) { + when (mcVersion.code) { in 12105..12110 -> "3.1.2+2a6ec84b49" 12111 -> "3.1.27+4fc5413f3e" 260100 -> "4.0.0+574290bac9" @@ -39,7 +39,7 @@ val fapiResourceLoader = Dependency( group = "net.fabricmc.fabric-api", name = "fabric-resource-loader-v0", version = { mcVersion -> - when (mcVersion) { + when (mcVersion.code) { 12105 -> "3.1.6+02ca679649" else -> throw IllegalStateException("$mcVersion is not yet supported!") } diff --git a/buildSrc/src/main/kotlin/dependencies/LexForge.kt b/buildSrc/src/main/kotlin/dependencies/LexForge.kt index dac39b98..a95de279 100644 --- a/buildSrc/src/main/kotlin/dependencies/LexForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/LexForge.kt @@ -4,7 +4,7 @@ val lexForge = Dependency( group = "net.minecraftforge", name = "forge", version = { mcVersion -> - val version = when (mcVersion) { + val version = when (mcVersion.code) { 11605 -> "36.2.41" 11802 -> "40.2.9" in 11900..11902 -> "43.2.14" @@ -13,6 +13,6 @@ val lexForge = Dependency( in 12002..12004 -> "48.0.13" else -> throw IllegalStateException("Forge no longer supported!") } - "${versionStr(mcVersion)}-${version}" + "${mcVersion}-${version}" }, ) diff --git a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt index 068c4c9a..abe260c3 100644 --- a/buildSrc/src/main/kotlin/dependencies/Minecraft.kt +++ b/buildSrc/src/main/kotlin/dependencies/Minecraft.kt @@ -4,11 +4,11 @@ val minecraft = Dependency( group = "com.mojang", name = "minecraft", version = { mcVersion -> - when (mcVersion) { + when (mcVersion.code) { // For snapshots //12100 -> "some snapshot" 260100 -> "26.1-snapshot-2" - else -> versionStr(mcVersion) + else -> mcVersion.string } }, ) diff --git a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt index 16388cff..ac2ecec6 100644 --- a/buildSrc/src/main/kotlin/dependencies/NeoForge.kt +++ b/buildSrc/src/main/kotlin/dependencies/NeoForge.kt @@ -4,7 +4,7 @@ val NEO = Dependency( group = "net.neoforged", name = "neoforge", version = { mcVersion -> - val version = when (mcVersion) { + val version = when (mcVersion.code) { // snapshot version format: // "0-alpha.${mc[mcVersion]}.+" in 12002..12003 -> "86" @@ -17,7 +17,10 @@ val NEO = Dependency( 260100 -> "0-alpha.4+snapshot-1" else -> throw IllegalStateException("Version $mcVersion is not yet supported!") } - val mc = versionStr(mcVersion, true).let { if (mcVersion>=260100) it else it.substring(2) } + val mc = mcVersion + .let { it.alwaysShowHotfix = true; it } + .string + .let { if (mcVersion.code >= 260100) it else it.substring(2) } "${mc}.${version}" }, diff --git a/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt b/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt index 7a4636c9..fe54f335 100644 --- a/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt +++ b/buildSrc/src/main/kotlin/dependencies/RecipeViewer.kt @@ -1,24 +1,26 @@ package dependencies -fun emi(mcVersion: Int, loader: String? = null, api: Boolean = false) = Dependency( +import CGVer + +fun emi(mcVersion: CGVer, loader: String? = null, api: Boolean = false) = Dependency( group = "dev.emi", name = if (loader != null) { // EMI migrate to NeoForge after 1.20.2 - if (loader != "fabric" && mcVersion <= 12002) "emi-forge" else "emi-$loader" + if (loader != "fabric" && mcVersion.code <= 12002) "emi-forge" else "emi-$loader" } else "emi", version = { _ -> buildString { - if (mcVersion <= 11802) { - append("0.7.3+${versionStr(mcVersion)}") // There are no multi-loader support in 1.18.2 + if (mcVersion.code <= 11802) { + append("0.7.3+$mcVersion") // There are no multi-loader support in 1.18.2 } else { append("1.1.21+") append( // They didn't break API on MC version upgrade so mismatch should be fine - when (mcVersion) { + when (mcVersion.code) { in 11900..11902 -> "1.19.2" - in 11903..11904 -> versionStr(mcVersion) + in 11903..11904 -> mcVersion.string in 12000..12001 -> "1.20.1" - 12002, 12004 -> versionStr(mcVersion) + 12002, 12004 -> mcVersion.string 12003 -> "1.20.2" in 12005..12006 -> "1.20.6" in 12100..12111 -> "1.21.1" @@ -41,7 +43,7 @@ fun rei(loader: String, api: Boolean = false) = Dependency( }, version = { mcVersion -> // They didn't break API on MC version upgrade so mismatch should be fine - when (mcVersion) { + when (mcVersion.code) { 11802 -> "8.3.618" in 11900..11902 -> "9.1.619" in 11903..11904 -> "11.0.621" @@ -57,19 +59,19 @@ fun rei(loader: String, api: Boolean = false) = Dependency( }, ) -fun jei(mcVersion: Int, loader: String, common: Boolean = false, api: Boolean = false) = Dependency( +fun jei(mcVersion: CGVer, loader: String, common: Boolean = false, api: Boolean = false) = Dependency( group = "mezz.jei", name = buildString { append("jei-") append( // They didn't break API on MC version upgrade so mismatch should be fine - when (mcVersion) { - 11802 -> versionStr(mcVersion) + when (mcVersion.code) { + 11802 -> mcVersion.string in 11900..11903 -> "1.19.2" - 11904 -> versionStr(mcVersion) + 11904 -> mcVersion.string in 12000..12001 -> "1.20.1" in 12002..12004 -> "1.20.2" - in 12005..12006 -> versionStr(mcVersion) + in 12005..12006 -> mcVersion.string in 12100..12110 -> "1.21.1" 12111 -> "1.21.11" 260100 -> "1.21.11" @@ -81,7 +83,7 @@ fun jei(mcVersion: Int, loader: String, common: Boolean = false, api: Boolean = append("-common") } else { append("-") - if (loader != "fabric" && mcVersion < 12100) append("forge") + if (loader != "fabric" && mcVersion.code < 12100) append("forge") else append(loader) } append ("-api") @@ -89,7 +91,7 @@ fun jei(mcVersion: Int, loader: String, common: Boolean = false, api: Boolean = }, version = { _ -> // They didn't break API on MC version upgrade so mismatch should be fine - when (mcVersion) { + when (mcVersion.code) { 11802 -> "10.2.1.1009" in 11900..11903 -> "11.8.1.1034" 11904 -> "13.1.0.13" diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index a13875b4..2b9c9ba7 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -10,8 +10,7 @@ import net.neoforged.moddevgradle.legacyforge.dsl.MixinExtension import net.neoforged.moddevgradle.legacyforge.dsl.ObfuscationExtension import net.neoforged.moddevgradle.tasks.JarJar -val mcVersion = ext["mcVersion"] as Int -val mcVersionStr = ext["mcVersionStr"] as String +val mcVersion = ext["mcVersion"] as CGVer val loaderName = ext["loaderName"] as String val isFabric = ext["isFabric"] as Boolean val isForge = ext["isForge"] as Boolean @@ -24,7 +23,7 @@ fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit assert(isLoom()) { "This project didn't use Loom!" } project.the() .apply { - if (mcVersion >= 12105) { + if (mcVersion.code >= 12105) { accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") } @@ -67,7 +66,7 @@ fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit */ environment("gameTestServer") forgeTemplate("gameTestServer") - if (mcVersion >= 12111) { + if (mcVersion.code >= 12111) { // REF: https://github.com/neoforged/NeoForge/blob/af6abbe00ab3071ad58c2cb70b988cb79f0b4af8/buildSrc/src/main/java/net/neoforged/neodev/CreateUserDevConfig.java#L128 defaultMainClass = "net.neoforged.fml.startup.GameTestServer" } @@ -90,7 +89,7 @@ inline fun GradlePlugin.configureNeo(configuration: project.the() .apply { // FIXME: AccessWidener to AccessTransformer - validateAccessTransformers = mcVersion >= 12105 + validateAccessTransformers = mcVersion.code >= 12105 runs { create("client") { @@ -163,7 +162,7 @@ dependencies { // Mainly for testing // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env // REF: https://github.com/FabricMC/fabric/issues/4491 - if (mcVersion in 11606..12104) { + if (mcVersion.code in 11606..12104) { dep("modLocalRuntime", fapi.versioned(mcVersion)) } else { try { @@ -174,7 +173,7 @@ dependencies { } } - if (mcVersion >= 260100) { + if (mcVersion.code >= 260100) { // FIXME: For some reason mixin is missing? dep("compileOnly", "org.spongepowered:mixin:0.8.7") } @@ -189,7 +188,7 @@ dependencies { annotationProcessor("org.spongepowered:mixin:0.8.7:processor") } - if (mcVersion > 11605) { + if (mcVersion.code > 11605) { // TODO: Maybe it's no longer needed since we can just use ':stubs'? // We just want their source code so we can mixin it if (isFabric) { @@ -200,15 +199,15 @@ dependencies { } // <- EMI - if (mcVersion <= 11802) { - dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(0)) + if (mcVersion.code <= 11802) { + dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(CGVer.wildcard())) if (project.properties["recipe_viewer"] == "emi" && isFabric) - dep("modLocalRuntime", emi(mcVersion).versioned(0)) + dep("modLocalRuntime", emi(mcVersion).versioned(CGVer.wildcard())) } else { - if (mcVersion <= 12105) { - dep("modCompileOnly", emi(mcVersion, loaderName, api = true).versioned(0)) + if (mcVersion.code <= 12105) { + dep("modCompileOnly", emi(mcVersion, loaderName, api = true).versioned(CGVer.wildcard())) if (project.properties["recipe_viewer"] == "emi") - dep("modLocalRuntime", emi(mcVersion, loaderName).versioned(0)) + dep("modLocalRuntime", emi(mcVersion, loaderName).versioned(CGVer.wildcard())) } } // EMI -> @@ -216,22 +215,22 @@ dependencies { // <- REI // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) - if ((isFabric && mcVersion in 12002..12104) || (isForge && mcVersion in 11802..12001)) { // FIXME: Not sure why it's not included + if ((isFabric && mcVersion.code in 12002..12104) || (isForge && mcVersion.code in 11802..12001)) { // FIXME: Not sure why it's not included dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") dep("modCompileOnly", "dev.architectury:architectury:11.1.13") } if (project.properties["recipe_viewer"] == "rei") { - if (mcVersion == 11902) // REI's stupid dep bug + if (mcVersion.code == 11902) // REI's stupid dep bug dep("modLocalRuntime", "dev.architectury:architectury-fabric:6.5.77") dep("modLocalRuntime", rei(loaderName).versioned(mcVersion)) } // REI -> // <- JEI - dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(0)) - dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(0)) + dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(CGVer.wildcard())) + dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(CGVer.wildcard())) if (project.properties["recipe_viewer"] == "jei") - dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(0)) + dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(CGVer.wildcard())) // JEI -> /* FIXME: Broken, somehow @@ -250,10 +249,10 @@ tasks.jar { )) } -if (mcVersion < 260100) { +if (mcVersion.code < 260100) { if (projectPlugin.isLoom()) tasks.withType { val shadowJar by tasks.getting(ShadowJar::class) - if (isForge && mcVersion >= 12105) { + if (isForge && mcVersion.code >= 12105) { atAccessWideners.add("cobblegen.accesswidener") } inputFile.set(shadowJar.archiveFile) @@ -265,7 +264,7 @@ if (mcVersion < 260100) { } } -if (mcVersion >= 260100 || !projectPlugin.isLoom()){ +if (mcVersion.code >= 260100 || !projectPlugin.isLoom()){ tasks.jar { archiveClassifier = "dev" } diff --git a/mclib/build.gradle.kts b/mclib/build.gradle.kts index d359bac6..1f66299b 100644 --- a/mclib/build.gradle.kts +++ b/mclib/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } minecraft { - version(MC.version(project.ext["mcVersion"] as Int)) + version(MC.version(project.ext["mcVersion"] as CGVer)) } repositories { diff --git a/stubs/build.gradle.kts b/stubs/build.gradle.kts index 7a7f845d..00dcc475 100644 --- a/stubs/build.gradle.kts +++ b/stubs/build.gradle.kts @@ -6,7 +6,7 @@ plugins { minecraft { //accessWideners(project(":mclib").file("")) - version(MC.version(project.ext["mcVersion"] as Int)) + version(MC.version(project.ext["mcVersion"] as CGVer)) } repositories { From 233eb359dfc184516f23a655928ce1963f2a9b31 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 10:12:13 +0700 Subject: [PATCH 77/92] ci: Fix build This is insanely confusing wtf? --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 150f1cd2..26210134 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -131,7 +131,7 @@ jobs: retention-days: 3 - name: GameTest with Gradle - if: github.event.inputs.bypass-test != 'true' && matrix.gradleGameTest + if: github.event.inputs.bypass-test != 'true' && matrix.gradleGameTest == 'true' run: | echo "# GameTest results" >> $GITHUB_STEP_SUMMARY; echo "
" >> $GITHUB_STEP_SUMMARY; From 60d270a1d82eeb055ec858ba99c73e657b55691f Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 10:16:18 +0700 Subject: [PATCH 78/92] ci: Nvm, action didn't run because there is a merge conflict, shoulda communicated that better GITHUB! --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 26210134..150f1cd2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -131,7 +131,7 @@ jobs: retention-days: 3 - name: GameTest with Gradle - if: github.event.inputs.bypass-test != 'true' && matrix.gradleGameTest == 'true' + if: github.event.inputs.bypass-test != 'true' && matrix.gradleGameTest run: | echo "# GameTest results" >> $GITHUB_STEP_SUMMARY; echo "
" >> $GITHUB_STEP_SUMMARY; From 1f8857cd41a32ac8e88754b66b5f85bc1edc4104 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 10:26:10 +0700 Subject: [PATCH 79/92] fix: Fix regression --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index b5d96d94..1dec871f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -50,7 +50,7 @@ val projectPlugin = when { fun setupPreprocessor() { val buildProps = buildString { append("# DON'T TOUCH THIS FILE, This is handled by the build script\n") - append("MC=${mcVersion}\n") + append("MC=${mcVersion.code}\n") if (isFabric) append("FABRIC=1\n") if (isForge) append("FORGE=${if (!isNeo) "1" else "2"}\n") } From 2b63514dae25f2aa1ce9fe207544f4b0db20c2e2 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 12:11:01 +0700 Subject: [PATCH 80/92] ci: Retry building with gradle 5 times --- .github/workflows/build.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 150f1cd2..f1753477 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -107,7 +107,25 @@ jobs: - name: Build with Gradle run: | - ./gradlew build -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}" + # Retry 5 times because TerraformersMC's Maven keep having a stroke + # and there's no way to workaround it through Gradle as there are no + # public API for it. So we just need to deal with it I guess. + # + # REF: https://discuss.gradle.org/t/how-to-deal-with-network-flakiness-impacting-gradle-builds/25705/3 + # REF: https://github.com/gradle/gradle/issues/4629 + # REF: https://github.com/gradle/gradle/issues/2779 + tries=1 + c="0" + while [ $tries -le 5 ]; + do + ./gradlew build -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}" && exit 0 + err="$?" + echo "Try $tries failed. (code:$err)" + sleep 5s + tries=$((tries+1)) + done + + [ "$err" = "0" ] || exit 1 env: VERSION: ${{ github.event.inputs.version == '' && '0.0.0' || github.event.inputs.version }} From 96dcfdf9fa0f942db70585efa75a5a87994eb8f6 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 12:19:52 +0700 Subject: [PATCH 81/92] ci: err should be c --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1753477..a6e18db6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,13 +119,13 @@ jobs: while [ $tries -le 5 ]; do ./gradlew build -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}" && exit 0 - err="$?" - echo "Try $tries failed. (code:$err)" + c="$?" + echo "Try $tries failed. (code:$c)" sleep 5s tries=$((tries+1)) done - [ "$err" = "0" ] || exit 1 + [ "$c" = "0" ] || exit 1 env: VERSION: ${{ github.event.inputs.version == '' && '0.0.0' || github.event.inputs.version }} From 1382f7234b4fda440e80342c348bde628287904a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 13:03:26 +0700 Subject: [PATCH 82/92] refactor: Add sourceSet instead of shadowing --- build.gradle.kts | 11 ----------- .../src/main/kotlin/multiloader.gradle.kts | 19 +++++++++++++++++++ cobblegen/build.gradle.kts | 10 +++++++++- gradle.properties | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 buildSrc/src/main/kotlin/multiloader.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts index 1dec871f..034c0786 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -229,17 +229,6 @@ subprojects { manifoldCompile("systems.manifold:manifold-preprocessor:${manifoldVersion}") if (isModModule) { - compileOnly(project(":stubs")) - compileInternal(project(":mclib")) { isTransitive = false } - shadeInternal(project(":mclib")) { - // Remove Junit test libraries - exclude(group = "org.junit.jupiter", module = "junit-jupiter") - exclude(group = "org.junit.jupiter", module = "junit-jupiter-engine") - exclude(group = "junit", module = "junit") - // Removed dependencies - isTransitive = false - } - if (mcVersion.code <= 11605) { // slf4j is not included by MC in 1.16.5 shade("org.slf4j:slf4j-api:1.7.36") diff --git a/buildSrc/src/main/kotlin/multiloader.gradle.kts b/buildSrc/src/main/kotlin/multiloader.gradle.kts new file mode 100644 index 00000000..b22886b6 --- /dev/null +++ b/buildSrc/src/main/kotlin/multiloader.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("java-library") +} + +dependencies { + compileOnly(project(":mclib")) +} + +tasks.compileJava { + source(project(":mclib").sourceSets.main.get().allSource) +} + +//tasks.sourcesJar { +// from(project(":mclib").sourceSets.main.get().allJava) +//} + +tasks.processResources { + from(project(":mclib").sourceSets.main.get().resources) +} diff --git a/cobblegen/build.gradle.kts b/cobblegen/build.gradle.kts index 2b9c9ba7..8f349850 100644 --- a/cobblegen/build.gradle.kts +++ b/cobblegen/build.gradle.kts @@ -10,6 +10,10 @@ import net.neoforged.moddevgradle.legacyforge.dsl.MixinExtension import net.neoforged.moddevgradle.legacyforge.dsl.ObfuscationExtension import net.neoforged.moddevgradle.tasks.JarJar +plugins { + id("multiloader") +} + val mcVersion = ext["mcVersion"] as CGVer val loaderName = ext["loaderName"] as String val isFabric = ext["isFabric"] as Boolean @@ -116,6 +120,7 @@ inline fun GradlePlugin.configureNeo(configuration: mods { create("${base.archivesName.get()}") { sourceSet(sourceSets.main.get()) + sourceSet(project(":mclib").sourceSets.main.get()) } } } @@ -188,8 +193,11 @@ dependencies { annotationProcessor("org.spongepowered:mixin:0.8.7:processor") } + // Bunch of dummy classes, just so that the mod compiles + compileOnly(project(":stubs")) + if (mcVersion.code > 11605) { - // TODO: Maybe it's no longer needed since we can just use ':stubs'? + // FIXME: RuntimeOnly // We just want their source code so we can mixin it if (isFabric) { // modCompileOnly("io.github.fabricators_of_create:Porting-Lib:${project.properties["port_lib_version_1_18_2"]}") diff --git a/gradle.properties b/gradle.properties index fcf385ce..e9e4714d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ create_version_1_18_2=0.5.1-f-build.1333+mc1.18.2 port_lib_version_1_18_2=1.2.869-beta+1.18.2 # Default MC version and loader name for IDEs, will be overwritten by gradle build argument -PmcVer or -PloaderName -mcVer=26.1 +mcVer=1.21.11 null2264.platform=fabric forge.enableGameTest=true neoforge.enableGameTest=true From 1a4ce057de01e2ae778a93f6bacbf29d45bfed81 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 13:29:15 +0700 Subject: [PATCH 83/92] fix: Increase -Xmx --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e9e4714d..0dea1d93 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -org.gradle.jvmargs=-Xmx6G +org.gradle.jvmargs=-Xmx8G # Mod Properties version_stage=BETA From a89cfb131a00c287d1ef682019af2edc821f17b1 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sat, 31 Jan 2026 18:32:34 +0700 Subject: [PATCH 84/92] refactor: WIP split --- build.gradle.kts | 186 ++++++++-------- buildSrc/src/main/kotlin/CGVer.kt | 2 + .../src/main/kotlin/ProcessModMetadata.kt | 31 ++- .../src/main/kotlin/multiloader.gradle.kts | 26 ++- fabric/README.md | 3 + fabric/build.gradle.kts | 204 ++++++++++++++++++ .../cobblegen/fabric/CobbleGenFabric.java | 10 + .../cobblegen/fabric}/CobbleGenPreLaunch.java | 2 +- .../CreateFluidReactionsMixin$PatchF.java | 0 .../main/resources/cobblegen.accesswidener | 0 .../resources/cobblegen.fabric.mixins.json | 18 ++ .../src/main/resources/fabric.mod.json | 5 +- forge/README.md | 4 + {cobblegen => forge}/build.gradle.kts | 146 ++----------- .../cobblegen/forge/CobbleGenForge.java | 20 ++ .../loader/neoforge/NetworkRegistryMixin.java | 0 .../resources/META-INF/accesstransformer.cfg | 1 + .../src/main/resources/META-INF/mods.toml | 3 + .../resources/META-INF/neoforge.mods.toml | 3 + .../resources/cobblegen.forge.mixins.json | 18 ++ .../src/main/resources/pack.mcmeta | 0 mclib/README.md | 3 - settings.gradle.kts | 5 +- xplat/README.md | 4 + {mclib => xplat}/build.gradle.kts | 18 ++ .../github/null2264/cobblegen/CGPlugin.java | 0 .../github/null2264/cobblegen/CobbleGen.java | 31 +-- .../null2264/cobblegen/CobbleGenPlugin.java | 0 .../null2264/cobblegen/FluidInteraction.java | 0 .../cobblegen/compat/CollectionCompat.java | 0 .../cobblegen/compat/GraphicsCompat.java | 0 .../cobblegen/compat/LoaderCompat.java | 0 .../cobblegen/compat/ModContainerCompat.java | 0 .../cobblegen/compat/RegistryCompat.java | 0 .../null2264/cobblegen/compat/TextCompat.java | 0 .../null2264/cobblegen/data/CGIdentifier.java | 0 .../null2264/cobblegen/data/CGModifier.java | 0 .../cobblegen/data/CGRegistryImpl.java | 0 .../cobblegen/data/JanksonSerializable.java | 0 .../github/null2264/cobblegen/data/Pair.java | 0 .../cobblegen/data/config/AdvancedGen.java | 0 .../cobblegen/data/config/Config.java | 0 .../cobblegen/data/config/ConfigData.java | 0 .../cobblegen/data/config/ConfigHelper.java | 0 .../cobblegen/data/config/ConfigMetaData.java | 0 .../cobblegen/data/config/CustomGen.java | 0 .../data/config/FluidInteractionMap.java | 0 .../cobblegen/data/config/GeneratorMap.java | 0 .../cobblegen/data/config/ResultList.java | 0 .../cobblegen/data/config/WeightedBlock.java | 0 .../data/generator/BasaltGenerator.java | 0 .../data/generator/CobbleGenerator.java | 0 .../data/generator/StoneGenerator.java | 0 .../cobblegen/data/model/BlockGenerator.java | 0 .../data/model/BuiltInGenerator.java | 0 .../cobblegen/data/model/CGRegistry.java | 0 .../cobblegen/data/model/Generator.java | 0 .../data/model/PacketSerializable.java | 0 .../network/FriendlyByteBuf/ByteBufExt.java | 0 .../minecraft/world/level/Level/LevelExt.java | 0 .../level/LevelAccessor/LevelAccessorExt.java | 0 .../gametest/BlockGenerationTest.java | 0 .../gametest/CobbleGenTestLoader.java | 0 .../cobblegen/gametest/Constants.java | 0 .../cobblegen/integration/BuiltInPlugin.java | 0 .../cobblegen/integration/CreatePlugin.java | 0 .../integration/create/CreateCompatUtil.java | 0 .../integration/create/CreateSupport.java | 0 .../viewer/FluidInteractionRecipeHolder.java | 0 .../integration/viewer/emi/CGEMIPlugin.java | 0 .../viewer/emi/FluidInteractionRecipe.java | 0 .../integration/viewer/jei/CGJEIPlugin.java | 0 .../viewer/jei/FluidInteractionCategory.java | 0 .../integration/viewer/rei/CGREIPlugin.java | 0 .../viewer/rei/FluidInteractionCategory.java | 0 .../viewer/rei/FluidInteractionRecipe.java | 0 .../null2264/cobblegen/mc/Constants.java | 0 .../cobblegen/mixin/CommandsMixin.java | 0 .../cobblegen/mixin/MinecraftServerMixin.java | 0 .../mixin/core/CobbleGenMixinPlugin.java | 0 .../CreateFluidReactionsMixin$OFive.java | 0 .../CreateFluidReactionsMixin$PatchE.java | 0 .../mixin/fluid/FlowingFluidEventMixin.java | 0 .../mixin/fluid/FluidEventMixin.java | 0 .../cobblegen/mixin/fluid/LavaEventMixin.java | 0 .../RegistryDataLoaderMixin$GameTest.java | 0 ...tructureTemplateManagerMixin$GameTest.java | 0 .../ClientCommonPacketListenerMixin.java | 0 .../mixin/network/ConnectionMixin.java | 0 .../mixin/network/PlayerManagerMixin.java | 0 .../ServerCommonPacketListenerMixin.java | 0 ...erverConfigurationPacketListenerMixin.java | 0 ...erverboundCustomPayloadPacketAccessor.java | 0 .../ClientboundCustomPayloadPacketMixin.java | 0 .../packet/CustomPacketPayloadMixin.java | 0 .../ServerboundCustomPayloadPacketMixin.java | 0 .../network/CGClientPlayNetworkHandler.java | 0 .../network/CGServerPlayNetworkHandler.java | 0 .../null2264/cobblegen/network/README.md | 0 .../network/payload/CGPacketPayload.java | 0 .../network/payload/CGPayloadReader.java | 0 .../network/payload/CGPingC2SPayload.java | 0 .../network/payload/CGPingS2CPayload.java | 0 .../network/payload/CGSyncC2SPayload.java | 0 .../network/payload/CGSyncS2CPayload.java | 0 .../github/null2264/cobblegen/util/CGLog.java | 0 .../null2264/cobblegen/util/Constants.java | 0 .../cobblegen/util/GeneratorType.java | 0 .../cobblegen/util/PayloadHelper.java | 0 .../null2264/cobblegen/util/PluginFinder.java | 0 .../github/null2264/cobblegen/util/Util.java | 0 .../assets/cobblegen/lang/en_us.json | 0 .../assets/cobblegen/textures/gui/jei.png | Bin .../src/main/resources/cobblegen.mixins.json | 0 .../src/main/resources/icon.png | Bin 115 files changed, 481 insertions(+), 262 deletions(-) create mode 100644 fabric/README.md create mode 100644 fabric/build.gradle.kts create mode 100644 fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java rename {cobblegen/src/main/java/io/github/null2264/cobblegen => fabric/src/main/java/io/github/null2264/cobblegen/fabric}/CobbleGenPreLaunch.java (87%) rename {cobblegen/src/main/java/io/github/null2264/cobblegen => fabric/src/main/java/io/github/null2264/cobblegen/fabric}/mixin/create/CreateFluidReactionsMixin$PatchF.java (100%) rename {cobblegen => fabric}/src/main/resources/cobblegen.accesswidener (100%) create mode 100644 fabric/src/main/resources/cobblegen.fabric.mixins.json rename {cobblegen => fabric}/src/main/resources/fabric.mod.json (90%) create mode 100644 forge/README.md rename {cobblegen => forge}/build.gradle.kts (53%) create mode 100644 forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java rename {cobblegen/src/main/java/io/github/null2264/cobblegen => forge/src/main/java/io/github/null2264/cobblegen/forge}/mixin/network/loader/neoforge/NetworkRegistryMixin.java (100%) rename {cobblegen => forge}/src/main/resources/META-INF/accesstransformer.cfg (64%) rename {cobblegen => forge}/src/main/resources/META-INF/mods.toml (95%) rename {cobblegen => forge}/src/main/resources/META-INF/neoforge.mods.toml (94%) create mode 100644 forge/src/main/resources/cobblegen.forge.mixins.json rename {cobblegen => forge}/src/main/resources/pack.mcmeta (100%) delete mode 100644 mclib/README.md create mode 100644 xplat/README.md rename {mclib => xplat}/build.gradle.kts (62%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/CGPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/CobbleGen.java (72%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/CobbleGenPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/compat/CollectionCompat.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/compat/GraphicsCompat.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/compat/RegistryCompat.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/compat/TextCompat.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/CGIdentifier.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/CGModifier.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/CGRegistryImpl.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/JanksonSerializable.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/Pair.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/AdvancedGen.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/Config.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/ConfigData.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/ConfigHelper.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/ConfigMetaData.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/CustomGen.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/FluidInteractionMap.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/GeneratorMap.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/ResultList.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/config/WeightedBlock.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/generator/BasaltGenerator.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/generator/CobbleGenerator.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/generator/StoneGenerator.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/model/BlockGenerator.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/model/BuiltInGenerator.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/model/CGRegistry.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/model/Generator.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/data/model/PacketSerializable.java (100%) rename {mclib => xplat}/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java (100%) rename {mclib => xplat}/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java (100%) rename {mclib => xplat}/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/gametest/BlockGenerationTest.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/gametest/CobbleGenTestLoader.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/gametest/Constants.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/BuiltInPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/create/CreateSupport.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/FluidInteractionRecipeHolder.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/CGJEIPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mc/Constants.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/CommandsMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/MinecraftServerMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$OFive.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FlowingFluidEventMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FluidEventMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/fluid/LavaEventMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/gametest/RegistryDataLoaderMixin$GameTest.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/gametest/StructureTemplateManagerMixin$GameTest.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/ClientCommonPacketListenerMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/ConnectionMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/PlayerManagerMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerCommonPacketListenerMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerConfigurationPacketListenerMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerboundCustomPayloadPacketAccessor.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ClientboundCustomPayloadPacketMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/CustomPacketPayloadMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ServerboundCustomPayloadPacketMixin.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/CGClientPlayNetworkHandler.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/CGServerPlayNetworkHandler.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/README.md (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/payload/CGPacketPayload.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/payload/CGPayloadReader.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingC2SPayload.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingS2CPayload.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncC2SPayload.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncS2CPayload.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/util/CGLog.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/util/Constants.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/util/GeneratorType.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/util/PayloadHelper.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java (100%) rename {cobblegen => xplat}/src/main/java/io/github/null2264/cobblegen/util/Util.java (100%) rename {cobblegen => xplat}/src/main/resources/assets/cobblegen/lang/en_us.json (100%) rename {cobblegen => xplat}/src/main/resources/assets/cobblegen/textures/gui/jei.png (100%) rename {cobblegen => xplat}/src/main/resources/cobblegen.mixins.json (100%) rename {cobblegen => xplat}/src/main/resources/icon.png (100%) diff --git a/build.gradle.kts b/build.gradle.kts index 034c0786..e279f6c9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,8 +11,6 @@ plugins { id(GradlePlugin.ArchLoom.id) version "1.13-SNAPSHOT" apply false id(GradlePlugin.Loom.id) version "1.15-SNAPSHOT" apply false id(GradlePlugin.LegacyLoom.id) version "1.15-SNAPSHOT" apply false - id(GradlePlugin.MDG.id) version "2.0.140" apply false - id(GradlePlugin.LegacyMDG.id) version "2.0.140" apply false id("com.gradleup.shadow") apply false id("me.modmuss50.mod-publish-plugin") version "1.1.0" } @@ -135,30 +133,30 @@ allprojects { subprojects { // NOTE: This here for when I finally split the API to its own module, hopefully on v6.0 val isApi = false; // APIs shouldn't contain anything Minecraft related - val isModModule = project == project(":cobblegen") + val isModModule = project in listOf(project(":fabric"), project(":forge")) apply(plugin = "java") apply(plugin = "com.gradleup.shadow") - if (isModModule) { - // NOTE: This must be set before archloom is applied! - if (projectPlugin is GradlePlugin.ArchLoom) { - extra.set("loom.platform", loaderName) - apply(plugin = "architectury-plugin") - } - apply(plugin = projectPlugin.id) - if (projectPlugin is GradlePlugin.ArchLoom) { - val arch = project.extensions["architectury"] as ArchitectPluginExtension - arch.loader(loaderName) - } - - if (projectPlugin.isLegacyLoom()) { - val loom = project.extensions["loom"] as LoomGradleExtension - loom.apply { - silentMojangMappingsLicense() - } - } - } +// if (isModModule) { +// // NOTE: This must be set before archloom is applied! +// if (projectPlugin is GradlePlugin.ArchLoom) { +// extra.set("loom.platform", loaderName) +// apply(plugin = "architectury-plugin") +// } +// apply(plugin = projectPlugin.id) +// if (projectPlugin is GradlePlugin.ArchLoom) { +// val arch = project.extensions["architectury"] as ArchitectPluginExtension +// arch.loader(loaderName) +// } +// +// if (projectPlugin.isLegacyLoom()) { +// val loom = project.extensions["loom"] as LoomGradleExtension +// loom.apply { +// silentMojangMappingsLicense() +// } +// } +// } val manifoldVersion = project.properties["manifold_version"] as? String ?: "" @@ -214,12 +212,6 @@ subprojects { dependencies { if (isModModule && projectPlugin.isLoom()) { - val minecraft by configurations - minecraft(MC.versioned(mcVersion)) - if (projectPlugin.isLegacyLoom()) { - val mappings by configurations - mappings(loom.officialMojangMappings()) - } } shade("blue.endless:jankson:${project.properties["jankson_version"]}") @@ -361,72 +353,72 @@ subprojects { // .map { if (it.isPreRelease) it.copy(preRelease = "Snapshot") else it }.distinct().map { it.toMojangString() }) //} -publishMods { - val mainProject = project(":cobblegen") - file.set(mainProject.file("build/libs/${rootProject.properties["archives_base_name"]}-${mainProject.version}.jar")) - val releaseVersions = mcVersions(versionRange) - displayName.set( - buildString { - append("[") - if (isFabric) { - append("FABRIC") - } else { - if (isNeo) append("NEOFORGE") else append("FORGE") - } - append(" MC") - append(releaseVersions[0]) - if (releaseVersions.size > 1) append("+") - append("]") - append(" v") - append(modVersion) - append("-") - append(rootProject.properties["version_stage"]) - if (mcVersion.code <= 11605) append(" (LITE)") - } - ) - changelog.set(System.getenv("CHANGELOG") ?: "Please visit our [releases](https://github.com/null2264/CobbleGen/releases) for a changelog") - version.set(mainProject.version.toString()) - if (isFabric) { - modLoaders.add("fabric") - modLoaders.add("quilt") - } else { - if (mcVersion.code <= 12002 && !isNeo) // No more LexForge, LexForge is too buggy - modLoaders.add("forge") - if (mcVersion.code == 12001 || isNeo) - modLoaders.add("neoforge") - } - type = when(rootProject.properties["version_stage"]) { - "ALPHA" -> ALPHA - "BETA" -> BETA - else -> STABLE - } - - val cfToken = System.getenv("CURSEFORGE") - if (cfToken != null) { - curseforge { - accessToken = cfToken - projectId.set(rootProject.properties["curseforge_project"] as String) - // Because CF did it the lazy way and just group every snapshot as a single snapshot - minecraftVersions = - releaseVersions - .map { if (it.isPreRelease) it.copy(preRelease = "Snapshot") else it } - .distinct() - .map { it.toMojangString() } - - embeds { - slug = "jankson" - } - } - } - - val mrToken = System.getenv("MODRINTH") - if (mrToken != null) { - modrinth { - accessToken = mrToken - projectId.set(rootProject.properties["modrinth_project"] as String) - - minecraftVersions = - releaseVersions.map { it.toMojangString() } - } - } -} +//publishMods { +// val mainProject = project(":cobblegen") +// file.set(mainProject.file("build/libs/${rootProject.properties["archives_base_name"]}-${mainProject.version}.jar")) +// val releaseVersions = mcVersions(versionRange) +// displayName.set( +// buildString { +// append("[") +// if (isFabric) { +// append("FABRIC") +// } else { +// if (isNeo) append("NEOFORGE") else append("FORGE") +// } +// append(" MC") +// append(releaseVersions[0]) +// if (releaseVersions.size > 1) append("+") +// append("]") +// append(" v") +// append(modVersion) +// append("-") +// append(rootProject.properties["version_stage"]) +// if (mcVersion.code <= 11605) append(" (LITE)") +// } +// ) +// changelog.set(System.getenv("CHANGELOG") ?: "Please visit our [releases](https://github.com/null2264/CobbleGen/releases) for a changelog") +// version.set(mainProject.version.toString()) +// if (isFabric) { +// modLoaders.add("fabric") +// modLoaders.add("quilt") +// } else { +// if (mcVersion.code <= 12002 && !isNeo) // No more LexForge, LexForge is too buggy +// modLoaders.add("forge") +// if (mcVersion.code == 12001 || isNeo) +// modLoaders.add("neoforge") +// } +// type = when(rootProject.properties["version_stage"]) { +// "ALPHA" -> ALPHA +// "BETA" -> BETA +// else -> STABLE +// } +// +// val cfToken = System.getenv("CURSEFORGE") +// if (cfToken != null) { +// curseforge { +// accessToken = cfToken +// projectId.set(rootProject.properties["curseforge_project"] as String) +// // Because CF did it the lazy way and just group every snapshot as a single snapshot +// minecraftVersions = +// releaseVersions +// .map { if (it.isPreRelease) it.copy(preRelease = "Snapshot") else it } +// .distinct() +// .map { it.toMojangString() } +// +// embeds { +// slug = "jankson" +// } +// } +// } +// +// val mrToken = System.getenv("MODRINTH") +// if (mrToken != null) { +// modrinth { +// accessToken = mrToken +// projectId.set(rootProject.properties["modrinth_project"] as String) +// +// minecraftVersions = +// releaseVersions.map { it.toMojangString() } +// } +// } +//} diff --git a/buildSrc/src/main/kotlin/CGVer.kt b/buildSrc/src/main/kotlin/CGVer.kt index e33c9478..b0196f7b 100644 --- a/buildSrc/src/main/kotlin/CGVer.kt +++ b/buildSrc/src/main/kotlin/CGVer.kt @@ -1,3 +1,5 @@ +import org.gradle.kotlin.dsl.provideDelegate + data class CGVer( val code: Int, var alwaysShowHotfix: Boolean = false, diff --git a/buildSrc/src/main/kotlin/ProcessModMetadata.kt b/buildSrc/src/main/kotlin/ProcessModMetadata.kt index 9190f28a..9dbcd946 100644 --- a/buildSrc/src/main/kotlin/ProcessModMetadata.kt +++ b/buildSrc/src/main/kotlin/ProcessModMetadata.kt @@ -27,6 +27,36 @@ fun File.processModsToml( writeText(modsTomlContent) } +fun File.processMixinsJsonFabric(mcVersion: CGVer) { + val both = buildList { + if (mcVersion.code > 11605) { + addJson("create.CreateFluidReactionsMixin\$PatchF") + } + } + val mixinsJson = JsonObject( + lenientJson.decodeFromString(readText(Charsets.UTF_8)).toMutableMap().apply { + set("compatibilityLevel", JsonPrimitive(if (mcVersion.code <= 11605) "JAVA_8" else "JAVA_17")) + set("mixins", JsonArray(both)) + set("client", JsonArray(listOf())) + set("server", JsonArray(listOf())) + } + ) +} + +fun File.processMixinsJsonForge(mcVersion: CGVer) { + val server = buildList { + if (mcVersion.code >= 12004) addJson("network.loader.neoforge.NetworkRegistryMixin") + } + val mixinsJson = JsonObject( + lenientJson.decodeFromString(readText(Charsets.UTF_8)).toMutableMap().apply { + set("compatibilityLevel", JsonPrimitive(if (mcVersion.code <= 11605) "JAVA_8" else "JAVA_17")) + set("mixins", JsonArray(listOf())) + set("client", JsonArray(listOf())) + set("server", JsonArray(server)) + } + ) +} + fun File.processMixinsJson(mcVersion: CGVer, isFabric: Boolean) { val both = buildList { if (mcVersion.code >= 12005) addJson("network.packet.CustomPacketPayloadMixin") @@ -35,7 +65,6 @@ fun File.processMixinsJson(mcVersion: CGVer, isFabric: Boolean) { if (mcVersion.code > 11605) { addJson("create.CreateFluidReactionsMixin\$OFive") addJson("create.CreateFluidReactionsMixin\$PatchE") - if (isFabric) addJson("create.CreateFluidReactionsMixin\$PatchF") } addJson("fluid.FlowingFluidEventMixin") addJson("fluid.FluidEventMixin") diff --git a/buildSrc/src/main/kotlin/multiloader.gradle.kts b/buildSrc/src/main/kotlin/multiloader.gradle.kts index b22886b6..80d9b2c8 100644 --- a/buildSrc/src/main/kotlin/multiloader.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader.gradle.kts @@ -2,18 +2,32 @@ plugins { id("java-library") } +val commonJava by configurations.creating { + isCanBeResolved = true +} +val commonResources by configurations.creating { + isCanBeResolved = true +} + dependencies { - compileOnly(project(":mclib")) + compileOnly(project(":xplat")) + commonJava(project(":xplat", "commonJava")) + commonResources(project(":xplat", "commonResources")) } tasks.compileJava { - source(project(":mclib").sourceSets.main.get().allSource) + dependsOn(commonJava) + source(commonJava) } -//tasks.sourcesJar { -// from(project(":mclib").sourceSets.main.get().allJava) -//} +tasks.named("sourcesJar") { + dependsOn(commonJava) + dependsOn(commonResources) + from(commonJava) + from(commonResources) +} tasks.processResources { - from(project(":mclib").sourceSets.main.get().resources) + dependsOn(commonResources) + from(commonResources) } diff --git a/fabric/README.md b/fabric/README.md new file mode 100644 index 00000000..c30ad796 --- /dev/null +++ b/fabric/README.md @@ -0,0 +1,3 @@ +# `:fabric` + +This module contains source code that depends on Fabric. diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts new file mode 100644 index 00000000..2720b18b --- /dev/null +++ b/fabric/build.gradle.kts @@ -0,0 +1,204 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import dependencies.* +import net.fabricmc.loom.task.RemapJarTask +import java.util.Locale +import net.fabricmc.loom.api.LoomGradleExtensionAPI + +plugins { + id("multiloader") + id(GradlePlugin.Loom.id) version "1.15-SNAPSHOT" apply false + id(GradlePlugin.LegacyLoom.id) version "1.15-SNAPSHOT" apply false +} + +//val mcVersion = ext["mcVersion"] as CGVer +//val loaderName = "fabric" +//val projectPlugin = if (mcVersion.code >= 260100) { +// GradlePlugin.Loom +//} else { +// GradlePlugin.LegacyLoom +//} +// +//group = project.properties["maven_group"] as String +// +//apply(plugin = projectPlugin.id) +// +//loom { +// if (mcVersion.code >= 12105) { +// accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") +// } +// +// runConfigs { +// named("client") { +// runDir = "../run/client" +// configName = "Fabric Client" +// //vmArg("-Dnull2264.cobblegen.gametest=true") +// ideConfigGenerated(true) +// } +// named("server") { +// runDir = "../run/server" +// configName = "Fabric Server" +// //vmArg("-Dnull2264.cobblegen.gametest=true") +// ideConfigGenerated(true) +// } +// register("gametest") { +// server() +// name("Server GameTest") +// +// vmArg("-Dnull2264.cobblegen.gametest=true") +// vmArg("-Dfabric-api.gametest") +// vmArg("-Dfabric-api.gametest.report-file=${rootProject.layout.buildDirectory.file("reports/junit.xml").get().getAsFile()}") +// +// runDir("../run/serverGameTest") +// ideConfigGenerated(false) // Mostly for CI +// } +// } +//} +// +//tasks.withType().configureEach { +// javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) +//} +// +//fun DependencyHandlerScope.dep(configuration: String, dependency: String) { +// add( +// configuration.let { +// if (projectPlugin.isLegacy) { +// it +// } else { +// it.replace("mod", "").replaceFirstChar { c -> c.lowercase(Locale.getDefault()) } +// } +// }, +// dependency, +// ) +//} +// +//dependencies { +// val minecraft by configurations +// minecraft(MC.versioned(mcVersion)) +// if (projectPlugin.isLegacy) { +// val mappings by configurations +// mappings(loom.officialMojangMappings()) +// } +// +// dep("modImplementation", "net.fabricmc:fabric-loader:0.18.4") +// +// // Mainly for testing +// // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env +// // REF: https://github.com/FabricMC/fabric/issues/4491 +// if (mcVersion.code in 11606..12104) { +// dep("modLocalRuntime", fapi.versioned(mcVersion)) +// } else { +// try { +// // FIXME: Is Resource Loader even needed? +// //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) +// dep("modLocalRuntime", fapiGameTest.versioned(mcVersion)) +// } catch (_: IllegalStateException) { +// } +// } +// +// if (mcVersion.code >= 260100) { +// // FIXME: For some reason mixin is missing? +// dep("compileOnly", "org.spongepowered:mixin:0.8.7") +// } +// +// // Bunch of dummy classes, just so that the mod compiles +// compileOnly(project(":stubs")) +// +// if (mcVersion.code > 11605) { +// // FIXME: RuntimeOnly +// // We just want their source code so we can mixin it +// // modCompileOnly("io.github.fabricators_of_create:Porting-Lib:${project.properties["port_lib_version_1_18_2"]}") +// // modCompileOnly("com.simibubi.create:create-fabric-${project.properties["minecraft_version_1_18_2"]}:${project.properties["create_version_1_18_2"]}") +// +// // <- EMI +// if (mcVersion.code <= 11802) { +// dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(CGVer.wildcard())) +// if (project.properties["recipe_viewer"] == "emi") +// dep("modLocalRuntime", emi(mcVersion).versioned(CGVer.wildcard())) +// } else { +// if (mcVersion.code <= 12105) { +// dep("modCompileOnly", emi(mcVersion, loaderName, api = true).versioned(CGVer.wildcard())) +// if (project.properties["recipe_viewer"] == "emi") +// dep("modLocalRuntime", emi(mcVersion, loaderName).versioned(CGVer.wildcard())) +// } +// } +// // EMI -> +// +// // <- REI +// // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* +// dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) +// if (mcVersion.code in 12002..12104) { // FIXME: Not sure why it's not included +// dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") +// dep("modCompileOnly", "dev.architectury:architectury:11.1.13") +// } +// if (project.properties["recipe_viewer"] == "rei") { +// if (mcVersion.code == 11902) // REI's stupid dep bug +// dep("modLocalRuntime", "dev.architectury:architectury-fabric:6.5.77") +// dep("modLocalRuntime", rei(loaderName).versioned(mcVersion)) +// } +// // REI -> +// +// // <- JEI +// dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(CGVer.wildcard())) +// dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(CGVer.wildcard())) +// if (project.properties["recipe_viewer"] == "jei") +// dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(CGVer.wildcard())) +// // JEI -> +// +// /* FIXME: Broken, somehow +// if (mcVersion == 11802 && isFabric) { +// modLocalRuntime("com.tterrag.registrate_fabric:Registrate:MC1.18.2-1.1.7") +// modLocalRuntime("io.github.fabricators_of_create:Porting-Lib:${project.port_lib_version_1_18_2}") +// modLocalRuntime("com.simibubi.create:create-fabric-${project.minecraft_version_1_18_2}:${project.create_version_1_18_2}") +// } +// */ +// } +//} +// +//tasks.jar { +// manifest.attributes(mapOf( +// "Contains-Sources" to "java,class", +// "MixinConfigs" to "cobblegen.mixins.json", +// )) +//} +// +//if (projectPlugin.isLegacy) { +// tasks.withType { +// val shadowJar by tasks.getting(ShadowJar::class) +// inputFile.set(shadowJar.archiveFile) +// } +//} else { +// tasks.jar { +// archiveClassifier = "dev" +// } +// +// val productionJar by tasks.register("productionJar") { +// dependsOn(tasks.jar) +// archiveClassifier = "" +// archiveExtension = "jar" +// destinationDirectory = layout.buildDirectory.dir("libs") +// from(zipTree(tasks.shadowJar.flatMap { it.archiveFile })) +// } +// +// tasks.assemble { +// dependsOn(productionJar) +// } +//} + +//val deleteResources by tasks.creating(Delete::class) { +// delete(file("build/resources/main")) +//} + +//tasks.processResources { +// dependsOn(tasks.named("copyCommonLoaderResources")) +//} + +//tasks.getting(RunGameTask::class) { +// dependsOn(tasks.named("copyCommonLoaderResources")) +// finalizedBy(deleteResources) +//} + +//tasks.sourcesJar { +// val commonSources = project(":common").tasks.sourcesJar.get() +// dependsOn(commonSources) +// from(commonSources.archiveFile.map { zipTree(it) }) +//} diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java new file mode 100644 index 00000000..9e15f08e --- /dev/null +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java @@ -0,0 +1,10 @@ +package io.github.null2264.cobblegen.fabric; + +import io.github.null2264.cobblegen.CobbleGen; + +public class CobbleGenFabric extends CobbleGen implements net.fabricmc.api.ModInitializer { + @Override + public void onInitialize() { + super.init(); + } +} diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGenPreLaunch.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java similarity index 87% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGenPreLaunch.java rename to fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java index 19b7ef21..f9dc82ba 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGenPreLaunch.java +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java @@ -1,5 +1,5 @@ #if FABRIC -package io.github.null2264.cobblegen; +package io.github.null2264.cobblegen.fabric; public class CobbleGenPreLaunch implements net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint { public CobbleGenPreLaunch() { diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchF.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/create/CreateFluidReactionsMixin$PatchF.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchF.java rename to fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/create/CreateFluidReactionsMixin$PatchF.java diff --git a/cobblegen/src/main/resources/cobblegen.accesswidener b/fabric/src/main/resources/cobblegen.accesswidener similarity index 100% rename from cobblegen/src/main/resources/cobblegen.accesswidener rename to fabric/src/main/resources/cobblegen.accesswidener diff --git a/fabric/src/main/resources/cobblegen.fabric.mixins.json b/fabric/src/main/resources/cobblegen.fabric.mixins.json new file mode 100644 index 00000000..36533336 --- /dev/null +++ b/fabric/src/main/resources/cobblegen.fabric.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "io.github.null2264.cobblegen.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + // Will be added by build script (build.gradle.kts) + ], + "client": [ + // Will be added by build script (build.gradle.kts) + ], + "server": [ + // Will be added by build script (build.gradle.kts) + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/cobblegen/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json similarity index 90% rename from cobblegen/src/main/resources/fabric.mod.json rename to fabric/src/main/resources/fabric.mod.json index 39cd201c..05352967 100644 --- a/cobblegen/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -17,10 +17,10 @@ "environment": "*", "entrypoints": { "preLaunch": [ - "io.github.null2264.cobblegen.CobbleGenPreLaunch" + "io.github.null2264.cobblegen.fabric.CobbleGenPreLaunch" ], "main": [ - "io.github.null2264.cobblegen.CobbleGen" + "io.github.null2264.cobblegen.fabric.CobbleGenFabric" ], "jei_mod_plugin": [ // Will be added by build script (build.gradle.kts) @@ -39,6 +39,7 @@ ] }, "mixins": [ + "cobblegen.fabric.mixins.json", "cobblegen.mixins.json" ], "custom": { diff --git a/forge/README.md b/forge/README.md new file mode 100644 index 00000000..5699f4c9 --- /dev/null +++ b/forge/README.md @@ -0,0 +1,4 @@ +# `:forge` + +This module contains source code that depends on (Neo)Forge. This submodule handles Forge for 1.16.5 up to 1.20.1, +and NeoForge after 1.20.1. There are no Forge support for 1.20.2 onwards and there won't be any in the future. diff --git a/cobblegen/build.gradle.kts b/forge/build.gradle.kts similarity index 53% rename from cobblegen/build.gradle.kts rename to forge/build.gradle.kts index 8f349850..52eb0982 100644 --- a/cobblegen/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,8 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dependencies.* -import net.fabricmc.loom.task.RemapJarTask import java.util.Locale -import net.fabricmc.loom.api.LoomGradleExtensionAPI import net.neoforged.moddevgradle.dsl.ModDevExtension import net.neoforged.moddevgradle.dsl.NeoForgeExtension import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension @@ -12,82 +10,22 @@ import net.neoforged.moddevgradle.tasks.JarJar plugins { id("multiloader") + id(GradlePlugin.MDG.id) version "2.0.140" apply false + id(GradlePlugin.LegacyMDG.id) version "2.0.140" apply false } val mcVersion = ext["mcVersion"] as CGVer val loaderName = ext["loaderName"] as String -val isFabric = ext["isFabric"] as Boolean -val isForge = ext["isForge"] as Boolean -val isNeo = ext["isNeo"] as Boolean -val projectPlugin = extra["projectPlugin"] as GradlePlugin +val isNeo = mcVersion.code >= 12002 +val projectPlugin = if (mcVersion.code >= 12002) { + GradlePlugin.MDG +} else { + GradlePlugin.LegacyMDG +} group = project.properties["maven_group"] as String -fun GradlePlugin.configureLoom(configuration: LoomGradleExtensionAPI.() -> Unit = {}) { - assert(isLoom()) { "This project didn't use Loom!" } - project.the() - .apply { - if (mcVersion.code >= 12105) { - accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") - } - - runConfigs { - named("client") { - runDir = "../run/client" - configName = (if (isFabric) "Fabric" else if (!isNeo) "Forge" else "NeoForge") + " Client" - //vmArg("-Dnull2264.cobblegen.gametest=true") - ideConfigGenerated(true) - } - named("server") { - runDir = "../run/server" - configName = (if (isFabric) "Fabric" else if (!isNeo) "Forge" else "NeoForge") + " Server" - //vmArg("-Dnull2264.cobblegen.gametest=true") - ideConfigGenerated(true) - } - register("gametest") { - server() - name("Server GameTest") - - vmArg("-Dnull2264.cobblegen.gametest=true") - vmArg("-Dfabric-api.gametest") - vmArg("-Dfabric-api.gametest.report-file=${rootProject.layout.buildDirectory.file("reports/junit.xml").get().getAsFile()}") - // For Forge-alike - property("$loaderName.enabledGameTestNamespaces", "cobblegen") - property("$loaderName.gameTestServer", "true") - property("$loaderName.enableGameTest", "true") - - runDir("../run/serverGameTest") - ideConfigGenerated(false) // Mostly for CI - if (isNeo) { - /* - * Apparently this replicate NeoGradle's - * - * runs { - * gameTest { - * type = "gameTestServer" - * } - * } - */ - environment("gameTestServer") - forgeTemplate("gameTestServer") - if (mcVersion.code >= 12111) { - // REF: https://github.com/neoforged/NeoForge/blob/af6abbe00ab3071ad58c2cb70b988cb79f0b4af8/buildSrc/src/main/java/net/neoforged/neodev/CreateUserDevConfig.java#L128 - defaultMainClass = "net.neoforged.fml.startup.GameTestServer" - } - } - } - } - - if (!isFabric && !isNeo) { - forge { - mixinConfigs = listOf( - "cobblegen.mixins.json" - ) - } - } - } - .configuration() -} +apply(plugin = projectPlugin.id) inline fun GradlePlugin.configureNeo(configuration: T.() -> Unit = {}) { project.the() @@ -120,7 +58,7 @@ inline fun GradlePlugin.configureNeo(configuration: mods { create("${base.archivesName.get()}") { sourceSet(sourceSets.main.get()) - sourceSet(project(":mclib").sourceSets.main.get()) + sourceSet(project(":xplat").sourceSets.main.get()) } } } @@ -136,8 +74,7 @@ inline fun GradlePlugin.configureNeo(configuration: } } -if (projectPlugin.isLoom()) projectPlugin.configureLoom() -else if (projectPlugin.isLegacy) projectPlugin.configureNeo { +if (projectPlugin.isLegacy) projectPlugin.configureNeo { version = lexForge.version(mcVersion) } else projectPlugin.configureNeo { version = NEO.version(mcVersion) @@ -161,34 +98,7 @@ fun DependencyHandlerScope.dep(configuration: String, dependency: String) { } dependencies { - if (isFabric) { - dep("modImplementation", "net.fabricmc:fabric-loader:0.18.4") - - // Mainly for testing - // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env - // REF: https://github.com/FabricMC/fabric/issues/4491 - if (mcVersion.code in 11606..12104) { - dep("modLocalRuntime", fapi.versioned(mcVersion)) - } else { - try { - // FIXME: Is Resource Loader even needed? - //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) - dep("modLocalRuntime", fapiGameTest.versioned(mcVersion)) - } catch (e: IllegalStateException) { - } - } - - if (mcVersion.code >= 260100) { - // FIXME: For some reason mixin is missing? - dep("compileOnly", "org.spongepowered:mixin:0.8.7") - } - } else if (projectPlugin.isLoom()) { - if (!isNeo) { - "forge"(lexForge.versioned(mcVersion)) - } else { - "neoForge"(NEO.versioned(mcVersion)) - } - } else if (projectPlugin.isLegacy) { + if (projectPlugin.isLegacy) { // needed for legacy forge, for mapping stuff annotationProcessor("org.spongepowered:mixin:0.8.7:processor") } @@ -199,17 +109,12 @@ dependencies { if (mcVersion.code > 11605) { // FIXME: RuntimeOnly // We just want their source code so we can mixin it - if (isFabric) { - // modCompileOnly("io.github.fabricators_of_create:Porting-Lib:${project.properties["port_lib_version_1_18_2"]}") - // modCompileOnly("com.simibubi.create:create-fabric-${project.properties["minecraft_version_1_18_2"]}:${project.properties["create_version_1_18_2"]}") - } else { - // modCompileOnly(createMod(isNeo).versioned(0)) { isTransitive = false } - } + // modCompileOnly(createMod(isNeo).versioned(0)) { isTransitive = false } // <- EMI if (mcVersion.code <= 11802) { dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(CGVer.wildcard())) - if (project.properties["recipe_viewer"] == "emi" && isFabric) + if (project.properties["recipe_viewer"] == "emi") dep("modLocalRuntime", emi(mcVersion).versioned(CGVer.wildcard())) } else { if (mcVersion.code <= 12105) { @@ -223,7 +128,7 @@ dependencies { // <- REI // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) - if ((isFabric && mcVersion.code in 12002..12104) || (isForge && mcVersion.code in 11802..12001)) { // FIXME: Not sure why it's not included + if (mcVersion.code in 11802..12001) { // FIXME: Not sure why it's not included dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") dep("modCompileOnly", "dev.architectury:architectury:11.1.13") } @@ -253,26 +158,17 @@ dependencies { tasks.jar { manifest.attributes(mapOf( + "Contains-Sources" to "java,class", "MixinConfigs" to "cobblegen.mixins.json", )) } -if (mcVersion.code < 260100) { - if (projectPlugin.isLoom()) tasks.withType { - val shadowJar by tasks.getting(ShadowJar::class) - if (isForge && mcVersion.code >= 12105) { - atAccessWideners.add("cobblegen.accesswidener") - } - inputFile.set(shadowJar.archiveFile) - } else if (projectPlugin.isLegacy) project.the().apply { - tasks.jar { - finalizedBy(tasks.named("reobfJar")) - } - reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) +if (projectPlugin.isLegacy) project.the().apply { + tasks.jar { + finalizedBy(tasks.named("reobfJar")) } -} - -if (mcVersion.code >= 260100 || !projectPlugin.isLoom()){ + reobfuscate(tasks.named("shadowJar"), sourceSets.main.get()) +} else { tasks.jar { archiveClassifier = "dev" } diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java new file mode 100644 index 00000000..5edf5aaa --- /dev/null +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java @@ -0,0 +1,20 @@ +package io.github.null2264.cobblegen.fabric; + +import io.github.null2264.cobblegen.CobbleGen; + +#if FORGE + #if FORGE==2 +@net.neoforged.fml.common.Mod(CobbleGen.MOD_ID) + #elif FORGE==1 +@net.minecraftforge.fml.common.Mod(CobbleGen.MOD_ID) + #endif +#endif +public class CobbleGenForge extends CobbleGen { + + public CobbleGenForge { + #if MC>=11801 && MC<12105 + // I was gonna do RegisterGameTestsEvent like a normal person, but there's a check that I need to bypass otherwise Forge won't register my test + net.minecraft.gametest.framework.GameTestRegistry.register(io.github.null2264.cobblegen.gametest.BlockGenerationTest.class); + #endif + } +} diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/loader/neoforge/NetworkRegistryMixin.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/network/loader/neoforge/NetworkRegistryMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/loader/neoforge/NetworkRegistryMixin.java rename to forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/network/loader/neoforge/NetworkRegistryMixin.java diff --git a/cobblegen/src/main/resources/META-INF/accesstransformer.cfg b/forge/src/main/resources/META-INF/accesstransformer.cfg similarity index 64% rename from cobblegen/src/main/resources/META-INF/accesstransformer.cfg rename to forge/src/main/resources/META-INF/accesstransformer.cfg index f0fa284f..ac883772 100644 --- a/cobblegen/src/main/resources/META-INF/accesstransformer.cfg +++ b/forge/src/main/resources/META-INF/accesstransformer.cfg @@ -1,4 +1,5 @@ public net.minecraft.resources.RegistryDataLoader$Loader +public net.minecraft.resources.RegistryDataLoader$Loader (Lnet/minecraft/resources/RegistryDataLoader$RegistryData;Lnet/minecraft/core/WritableRegistry;Ljava/util/Map;)V public net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager$Source public net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager$Source (Ljava/util/function/Function;Ljava/util/function/Supplier;)V diff --git a/cobblegen/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml similarity index 95% rename from cobblegen/src/main/resources/META-INF/mods.toml rename to forge/src/main/resources/META-INF/mods.toml index f33e4346..cf7b42f0 100644 --- a/cobblegen/src/main/resources/META-INF/mods.toml +++ b/forge/src/main/resources/META-INF/mods.toml @@ -15,6 +15,9 @@ description = "An MC mod that allows you to customize cobblestone (stone and bas [[mixins]] config = "cobblegen.mixins.json" +[[mixins]] +config = "cobblegen.forge.mixins.json" + [[dependencies.cobblegen]] modId = "${forge}" mandatory = true diff --git a/cobblegen/src/main/resources/META-INF/neoforge.mods.toml b/forge/src/main/resources/META-INF/neoforge.mods.toml similarity index 94% rename from cobblegen/src/main/resources/META-INF/neoforge.mods.toml rename to forge/src/main/resources/META-INF/neoforge.mods.toml index fdf9010d..2dca24ac 100644 --- a/cobblegen/src/main/resources/META-INF/neoforge.mods.toml +++ b/forge/src/main/resources/META-INF/neoforge.mods.toml @@ -15,6 +15,9 @@ description = "An MC mod that allows you to customize cobblestone (stone and bas [[mixins]] config = "cobblegen.mixins.json" +[[mixins]] +config = "cobblegen.forge.mixins.json" + [[dependencies.cobblegen]] modId = "neoforge" mandatory = true diff --git a/forge/src/main/resources/cobblegen.forge.mixins.json b/forge/src/main/resources/cobblegen.forge.mixins.json new file mode 100644 index 00000000..36533336 --- /dev/null +++ b/forge/src/main/resources/cobblegen.forge.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "io.github.null2264.cobblegen.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + // Will be added by build script (build.gradle.kts) + ], + "client": [ + // Will be added by build script (build.gradle.kts) + ], + "server": [ + // Will be added by build script (build.gradle.kts) + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/cobblegen/src/main/resources/pack.mcmeta b/forge/src/main/resources/pack.mcmeta similarity index 100% rename from cobblegen/src/main/resources/pack.mcmeta rename to forge/src/main/resources/pack.mcmeta diff --git a/mclib/README.md b/mclib/README.md deleted file mode 100644 index f8718ef7..00000000 --- a/mclib/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# MCLib (`:mclib`) - -Library containing MC related stuff such as helper functions and extension methods diff --git a/settings.gradle.kts b/settings.gradle.kts index d8c8c7b6..df302d7d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,6 +37,7 @@ pluginManagement { rootProject.name = "CobbleGen" -include(":mclib") include(":stubs") -include(":cobblegen") // TODO: Maybe split? +include(":xplat") +include(":fabric") +include(":forge") diff --git a/xplat/README.md b/xplat/README.md new file mode 100644 index 00000000..02322085 --- /dev/null +++ b/xplat/README.md @@ -0,0 +1,4 @@ +# `:xplat` + +This module contains source code that can be shared across loader. This mod is designed to use only Vanilla features so +most of the work is done in this module. diff --git a/mclib/build.gradle.kts b/xplat/build.gradle.kts similarity index 62% rename from mclib/build.gradle.kts rename to xplat/build.gradle.kts index 1f66299b..1b08a531 100644 --- a/mclib/build.gradle.kts +++ b/xplat/build.gradle.kts @@ -1,6 +1,7 @@ import dependencies.minecraft as MC plugins { + id("java-library") id("org.spongepowered.gradle.vanilla") } @@ -12,10 +13,27 @@ repositories { maven("https://repo.spongepowered.org/maven/") } +configurations { + register("commonJava") { + isCanBeResolved = false + isCanBeConsumed = true + } + register("commonResources") { + isCanBeResolved = false + isCanBeConsumed = true + } +} + dependencies { + compileOnly(project(":stubs")) compileOnly("org.spongepowered:mixin:0.8.5") } +artifacts { + add("commonJava", sourceSets.main.get().java.sourceDirectories.singleFile) + add("commonResources", sourceSets.main.get().resources.sourceDirectories.singleFile) +} + publishing { publications { create("mavenCommon") { diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/CGPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/CGPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/CGPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/CGPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGen.java b/xplat/src/main/java/io/github/null2264/cobblegen/CobbleGen.java similarity index 72% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGen.java rename to xplat/src/main/java/io/github/null2264/cobblegen/CobbleGen.java index 4f07fa7f..70d44b84 100644 --- a/cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGen.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/CobbleGen.java @@ -10,20 +10,8 @@ import net.minecraft.commands.CommandSourceStack; import org.jetbrains.annotations.ApiStatus; -import static io.github.null2264.cobblegen.util.Constants.OP_LEVEL_GAMEMASTERS; +public abstract class CobbleGen { -#if FORGE - #if FORGE==2 -@net.neoforged.fml.common.Mod(CobbleGen.MOD_ID) - #elif FORGE==1 -@net.minecraftforge.fml.common.Mod(CobbleGen.MOD_ID) - #endif -#endif -public class CobbleGen -#if FABRIC - implements net.fabricmc.api.ModInitializer -#endif -{ public static final String MOD_ID = "cobblegen"; /** * @deprecated Only for internal usage. Use the parameter {@link CGRegistry registry} instead to register new Fluid Interaction @@ -32,20 +20,13 @@ public class CobbleGen @ApiStatus.Internal public static final FluidInteraction FLUID_INTERACTION = new FluidInteraction(); - public CobbleGen() { - // Force config to be generated when loading up the game instead of having to load a world + /* + * Force config to be generated when loading up the game instead of having to load a world + */ + public void init() { new ConfigData.Factory().load(); - #if FORGE && MC>=11801 && MC<12105 - // I was gonna do RegisterGameTestsEvent like a normal person, but there's a check that I need to bypass otherwise Forge won't register my test - net.minecraft.gametest.framework.GameTestRegistry.register(io.github.null2264.cobblegen.gametest.BlockGenerationTest.class); - #endif } - #if FABRIC - @Override - public void onInitialize() {} - #endif - public static void initCommands(CommandDispatcher dispatcher) { CGLog.info("Registering command..."); dispatcher.register( @@ -54,7 +35,7 @@ public static void initCommands(CommandDispatcher dispatcher LiteralArgumentBuilder. literal("reload-meta") #if MC<12111 - .requires(arg -> arg.hasPermission(OP_LEVEL_GAMEMASTERS)) + .requires(arg -> arg.hasPermission(io.github.null2264.cobblegen.util.Constants.OP_LEVEL_GAMEMASTERS)) #else .requires(net.minecraft.commands.Commands.hasPermission(net.minecraft.commands.Commands.LEVEL_GAMEMASTERS)) #endif diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGenPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/CobbleGenPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/CobbleGenPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/CobbleGenPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java b/xplat/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java rename to xplat/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/compat/CollectionCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/CollectionCompat.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/compat/CollectionCompat.java rename to xplat/src/main/java/io/github/null2264/cobblegen/compat/CollectionCompat.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/compat/GraphicsCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/GraphicsCompat.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/compat/GraphicsCompat.java rename to xplat/src/main/java/io/github/null2264/cobblegen/compat/GraphicsCompat.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java rename to xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java rename to xplat/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/compat/RegistryCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/RegistryCompat.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/compat/RegistryCompat.java rename to xplat/src/main/java/io/github/null2264/cobblegen/compat/RegistryCompat.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/compat/TextCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/TextCompat.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/compat/TextCompat.java rename to xplat/src/main/java/io/github/null2264/cobblegen/compat/TextCompat.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/CGIdentifier.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/CGIdentifier.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/CGIdentifier.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/CGIdentifier.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/CGModifier.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/CGModifier.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/CGModifier.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/CGModifier.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/CGRegistryImpl.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/CGRegistryImpl.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/CGRegistryImpl.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/CGRegistryImpl.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/JanksonSerializable.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/JanksonSerializable.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/JanksonSerializable.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/JanksonSerializable.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/Pair.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/Pair.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/Pair.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/Pair.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/AdvancedGen.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/AdvancedGen.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/AdvancedGen.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/AdvancedGen.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/Config.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/Config.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/Config.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/Config.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ConfigData.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/ConfigData.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ConfigData.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/ConfigData.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ConfigHelper.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/ConfigHelper.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ConfigHelper.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/ConfigHelper.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ConfigMetaData.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/ConfigMetaData.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ConfigMetaData.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/ConfigMetaData.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/CustomGen.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/CustomGen.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/CustomGen.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/CustomGen.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/FluidInteractionMap.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/FluidInteractionMap.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/FluidInteractionMap.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/FluidInteractionMap.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/GeneratorMap.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/GeneratorMap.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/GeneratorMap.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/GeneratorMap.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ResultList.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/ResultList.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/ResultList.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/ResultList.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/WeightedBlock.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/WeightedBlock.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/config/WeightedBlock.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/config/WeightedBlock.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/generator/BasaltGenerator.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/generator/BasaltGenerator.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/generator/BasaltGenerator.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/generator/BasaltGenerator.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/generator/CobbleGenerator.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/generator/CobbleGenerator.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/generator/CobbleGenerator.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/generator/CobbleGenerator.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/generator/StoneGenerator.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/generator/StoneGenerator.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/generator/StoneGenerator.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/generator/StoneGenerator.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/BlockGenerator.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/model/BlockGenerator.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/BlockGenerator.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/model/BlockGenerator.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/BuiltInGenerator.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/model/BuiltInGenerator.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/BuiltInGenerator.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/model/BuiltInGenerator.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/CGRegistry.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/model/CGRegistry.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/CGRegistry.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/model/CGRegistry.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/Generator.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/model/Generator.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/Generator.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/model/Generator.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/PacketSerializable.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/model/PacketSerializable.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/data/model/PacketSerializable.java rename to xplat/src/main/java/io/github/null2264/cobblegen/data/model/PacketSerializable.java diff --git a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java b/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java similarity index 100% rename from mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java rename to xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java diff --git a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java b/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java similarity index 100% rename from mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java rename to xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java diff --git a/mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java b/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java similarity index 100% rename from mclib/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java rename to xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/gametest/BlockGenerationTest.java b/xplat/src/main/java/io/github/null2264/cobblegen/gametest/BlockGenerationTest.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/gametest/BlockGenerationTest.java rename to xplat/src/main/java/io/github/null2264/cobblegen/gametest/BlockGenerationTest.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/gametest/CobbleGenTestLoader.java b/xplat/src/main/java/io/github/null2264/cobblegen/gametest/CobbleGenTestLoader.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/gametest/CobbleGenTestLoader.java rename to xplat/src/main/java/io/github/null2264/cobblegen/gametest/CobbleGenTestLoader.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/gametest/Constants.java b/xplat/src/main/java/io/github/null2264/cobblegen/gametest/Constants.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/gametest/Constants.java rename to xplat/src/main/java/io/github/null2264/cobblegen/gametest/Constants.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/BuiltInPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/BuiltInPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/BuiltInPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/BuiltInPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/create/CreateSupport.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateSupport.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/create/CreateSupport.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateSupport.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/FluidInteractionRecipeHolder.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/FluidInteractionRecipeHolder.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/FluidInteractionRecipeHolder.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/FluidInteractionRecipeHolder.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/CGEMIPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/emi/FluidInteractionRecipe.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/CGJEIPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/CGJEIPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/CGJEIPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/CGJEIPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/CGREIPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionCategory.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java rename to xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/rei/FluidInteractionRecipe.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mc/Constants.java b/xplat/src/main/java/io/github/null2264/cobblegen/mc/Constants.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mc/Constants.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mc/Constants.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/CommandsMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/CommandsMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/CommandsMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/CommandsMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/MinecraftServerMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/MinecraftServerMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/MinecraftServerMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/MinecraftServerMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$OFive.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$OFive.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$OFive.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$OFive.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FlowingFluidEventMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FlowingFluidEventMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FlowingFluidEventMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FlowingFluidEventMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FluidEventMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FluidEventMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FluidEventMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/fluid/FluidEventMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/fluid/LavaEventMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/fluid/LavaEventMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/fluid/LavaEventMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/fluid/LavaEventMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/gametest/RegistryDataLoaderMixin$GameTest.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/gametest/RegistryDataLoaderMixin$GameTest.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/gametest/RegistryDataLoaderMixin$GameTest.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/gametest/RegistryDataLoaderMixin$GameTest.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/gametest/StructureTemplateManagerMixin$GameTest.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/gametest/StructureTemplateManagerMixin$GameTest.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/gametest/StructureTemplateManagerMixin$GameTest.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/gametest/StructureTemplateManagerMixin$GameTest.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ClientCommonPacketListenerMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ClientCommonPacketListenerMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ClientCommonPacketListenerMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ClientCommonPacketListenerMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ConnectionMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ConnectionMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ConnectionMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ConnectionMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/PlayerManagerMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/PlayerManagerMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/PlayerManagerMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/PlayerManagerMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerCommonPacketListenerMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerCommonPacketListenerMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerCommonPacketListenerMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerCommonPacketListenerMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerConfigurationPacketListenerMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerConfigurationPacketListenerMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerConfigurationPacketListenerMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerConfigurationPacketListenerMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerboundCustomPayloadPacketAccessor.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerboundCustomPayloadPacketAccessor.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerboundCustomPayloadPacketAccessor.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/ServerboundCustomPayloadPacketAccessor.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ClientboundCustomPayloadPacketMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ClientboundCustomPayloadPacketMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ClientboundCustomPayloadPacketMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ClientboundCustomPayloadPacketMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/CustomPacketPayloadMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/CustomPacketPayloadMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/CustomPacketPayloadMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/CustomPacketPayloadMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ServerboundCustomPayloadPacketMixin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ServerboundCustomPayloadPacketMixin.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ServerboundCustomPayloadPacketMixin.java rename to xplat/src/main/java/io/github/null2264/cobblegen/mixin/network/packet/ServerboundCustomPayloadPacketMixin.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/CGClientPlayNetworkHandler.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/CGClientPlayNetworkHandler.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/CGClientPlayNetworkHandler.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/CGClientPlayNetworkHandler.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/CGServerPlayNetworkHandler.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/CGServerPlayNetworkHandler.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/CGServerPlayNetworkHandler.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/CGServerPlayNetworkHandler.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/README.md b/xplat/src/main/java/io/github/null2264/cobblegen/network/README.md similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/README.md rename to xplat/src/main/java/io/github/null2264/cobblegen/network/README.md diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPacketPayload.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPacketPayload.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPacketPayload.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPacketPayload.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPayloadReader.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPayloadReader.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPayloadReader.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPayloadReader.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingC2SPayload.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingC2SPayload.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingC2SPayload.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingC2SPayload.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingS2CPayload.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingS2CPayload.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingS2CPayload.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGPingS2CPayload.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncC2SPayload.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncC2SPayload.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncC2SPayload.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncC2SPayload.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncS2CPayload.java b/xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncS2CPayload.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncS2CPayload.java rename to xplat/src/main/java/io/github/null2264/cobblegen/network/payload/CGSyncS2CPayload.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/util/CGLog.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/CGLog.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/util/CGLog.java rename to xplat/src/main/java/io/github/null2264/cobblegen/util/CGLog.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/util/Constants.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/Constants.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/util/Constants.java rename to xplat/src/main/java/io/github/null2264/cobblegen/util/Constants.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/util/GeneratorType.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/GeneratorType.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/util/GeneratorType.java rename to xplat/src/main/java/io/github/null2264/cobblegen/util/GeneratorType.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/util/PayloadHelper.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/PayloadHelper.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/util/PayloadHelper.java rename to xplat/src/main/java/io/github/null2264/cobblegen/util/PayloadHelper.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java rename to xplat/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java diff --git a/cobblegen/src/main/java/io/github/null2264/cobblegen/util/Util.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/Util.java similarity index 100% rename from cobblegen/src/main/java/io/github/null2264/cobblegen/util/Util.java rename to xplat/src/main/java/io/github/null2264/cobblegen/util/Util.java diff --git a/cobblegen/src/main/resources/assets/cobblegen/lang/en_us.json b/xplat/src/main/resources/assets/cobblegen/lang/en_us.json similarity index 100% rename from cobblegen/src/main/resources/assets/cobblegen/lang/en_us.json rename to xplat/src/main/resources/assets/cobblegen/lang/en_us.json diff --git a/cobblegen/src/main/resources/assets/cobblegen/textures/gui/jei.png b/xplat/src/main/resources/assets/cobblegen/textures/gui/jei.png similarity index 100% rename from cobblegen/src/main/resources/assets/cobblegen/textures/gui/jei.png rename to xplat/src/main/resources/assets/cobblegen/textures/gui/jei.png diff --git a/cobblegen/src/main/resources/cobblegen.mixins.json b/xplat/src/main/resources/cobblegen.mixins.json similarity index 100% rename from cobblegen/src/main/resources/cobblegen.mixins.json rename to xplat/src/main/resources/cobblegen.mixins.json diff --git a/cobblegen/src/main/resources/icon.png b/xplat/src/main/resources/icon.png similarity index 100% rename from cobblegen/src/main/resources/icon.png rename to xplat/src/main/resources/icon.png From 44c980ed01fdf4ab67efb4c4f9983caddfd05db5 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sun, 1 Feb 2026 07:45:54 +0700 Subject: [PATCH 85/92] refactor: WIP split 2 --- build.gradle.kts | 94 +---- .../src/main/kotlin/ProcessModMetadata.kt | 6 +- fabric/build.gradle.kts | 359 +++++++++--------- forge/build.gradle.kts | 26 +- 4 files changed, 218 insertions(+), 267 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e279f6c9..cd2fcebd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,16 +1,9 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import dev.architectury.plugin.ArchitectPluginExtension -import net.fabricmc.loom.LoomGradleExtension -import net.fabricmc.loom.api.LoomGradleExtensionAPI -import dependencies.minecraft as MC import org.apache.tools.ant.filters.StripJavaComments plugins { id("java") id("architectury-plugin") version "3.4-SNAPSHOT" apply false - id(GradlePlugin.ArchLoom.id) version "1.13-SNAPSHOT" apply false - id(GradlePlugin.Loom.id) version "1.15-SNAPSHOT" apply false - id(GradlePlugin.LegacyLoom.id) version "1.15-SNAPSHOT" apply false id("com.gradleup.shadow") apply false id("me.modmuss50.mod-publish-plugin") version "1.1.0" } @@ -138,26 +131,6 @@ subprojects { apply(plugin = "java") apply(plugin = "com.gradleup.shadow") -// if (isModModule) { -// // NOTE: This must be set before archloom is applied! -// if (projectPlugin is GradlePlugin.ArchLoom) { -// extra.set("loom.platform", loaderName) -// apply(plugin = "architectury-plugin") -// } -// apply(plugin = projectPlugin.id) -// if (projectPlugin is GradlePlugin.ArchLoom) { -// val arch = project.extensions["architectury"] as ArchitectPluginExtension -// arch.loader(loaderName) -// } -// -// if (projectPlugin.isLegacyLoom()) { -// val loom = project.extensions["loom"] as LoomGradleExtension -// loom.apply { -// silentMojangMappingsLicense() -// } -// } -// } - val manifoldVersion = project.properties["manifold_version"] as? String ?: "" val shade: Configuration by configurations.creating { @@ -165,55 +138,21 @@ subprojects { } val shadeInternal: Configuration by configurations.creating - val loaderProd = when { - isFabric -> "Fabric" - isNeo -> "NeoForge" - isForge -> "Forge" - else -> throw IllegalStateException("Unknown loader!") - } - - // For internal libraries - val compileInternal: Configuration by configurations.creating { - configurations.compileClasspath.get().extendsFrom(this) - configurations.runtimeClasspath.get().extendsFrom(this) - if (isModModule && projectPlugin is GradlePlugin.ArchLoom) { - configurations["development$loaderProd"].extendsFrom(this) - } - afterEvaluate { - if (isModModule && mcVersion.code <= 12108 && !projectPlugin.isLoom()) { - configurations.named("additionalRuntimeClasspath").get().extendsFrom(this@creating) - } - } - } - val manifoldCompile: Configuration by configurations.creating { configurations.compileOnly.get().extendsFrom(this) configurations.annotationProcessor.get().extendsFrom(this) configurations.testAnnotationProcessor.get().extendsFrom(this) } - if (isModModule && !isFabric) { - if (projectPlugin.isLoom()) configurations.named("forgeRuntimeLibrary").get().extendsFrom(shade) - else { - afterEvaluate { - if (mcVersion.code <= 12108) { - configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) - } + if (project == project(":forge")) { + afterEvaluate { + if (mcVersion.code <= 12108) { + configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) } } } - val loom by lazy { - if (!isModModule) { - throw IllegalStateException("Loom only available for mod modules") - } - project.the() - } - dependencies { - if (isModModule && projectPlugin.isLoom()) { - } - shade("blue.endless:jankson:${project.properties["jankson_version"]}") shade("systems.manifold:manifold-ext-rt:${manifoldVersion}") @@ -254,24 +193,24 @@ subprojects { artifacts.add("archives", shadowJar) - val processResources by tasks.getting(ProcessResources::class) { - if (!isModModule) return@getting + tasks.withType { + if (!isModModule) return@withType val metadataVersion = "${modVersion}-${project.properties["version_stage"]}" - val metadataMCVersion = if (isForge) versionRange.mavenStyle() else versionRange.semverStyle() + val metadataMCVersion = if (project == project(":forge")) versionRange.mavenStyle() else versionRange.semverStyle() val properties = mapOf( "version" to metadataVersion, "mcversion" to metadataMCVersion, - "forge" to (if (isNeo) "neoforge" else "forge"), + "forge" to (if (mcVersion.code >= 12002) "neoforge" else "forge"), ) inputs.properties(properties) filteringCharset = Charsets.UTF_8.name() val metadataFilename = - if (isFabric) { + if (project == project(":fabric")) { "fabric.mod.json" } else { - if (isNeo && mcVersion.code >= 12006) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml" + if (mcVersion.code >= 12006) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml" } filesMatching(metadataFilename) { @@ -286,7 +225,7 @@ subprojects { doLast { // For some reason Mojang rename the structure directory on MC 1.21 to singular form val structureDirName = if (mcVersion.code >= 12100) "structure" else "structures" - if (isFabric || mcVersion.code >= 12105) { + if (project == project(":fabric") || mcVersion.code >= 12105) { project.file("build/resources/main/data/cobblegen/gametest/${structureDirName}/").mkdirs() project.file("build/resources/main/data/cobblegen/gametest/${structureDirName}/empty.snbt") .writeStructureAsSnbt(generateStructure(false)) @@ -296,12 +235,15 @@ subprojects { .writeStructureAsNbt(generateStructure(true)) } - project.file("build/resources/main/META-INF/mods.toml") - .processModsToml(mcVersion, if (!isForge) 0 else (if (isNeo) 2 else 1)) // We can't preprocess resources files with Manifold, so we'll construct the json files manually here instead. - project.file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion, isFabric) - if (isFabric) project.file("build/resources/main/fabric.mod.json").processFabricModJson(mcVersion) + project(":common").file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion) + project.file("build/resources/main/cobblegen.${project.name}.mixins.json").apply { + if (project == project(":fabric")) processMixinsJsonFabric(mcVersion) + else processMixinsJsonForge(mcVersion) + } + if (project == project(":fabric")) project.file("build/resources/main/fabric.mod.json").processFabricModJson(mcVersion) + else project.file("build/resources/main/$metadataFilename").processModsToml(mcVersion, if (mcVersion.code >= 12002) 2 else 1) } } diff --git a/buildSrc/src/main/kotlin/ProcessModMetadata.kt b/buildSrc/src/main/kotlin/ProcessModMetadata.kt index 9dbcd946..059fb3bf 100644 --- a/buildSrc/src/main/kotlin/ProcessModMetadata.kt +++ b/buildSrc/src/main/kotlin/ProcessModMetadata.kt @@ -1,8 +1,5 @@ import java.io.File -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive @@ -57,7 +54,7 @@ fun File.processMixinsJsonForge(mcVersion: CGVer) { ) } -fun File.processMixinsJson(mcVersion: CGVer, isFabric: Boolean) { +fun File.processMixinsJson(mcVersion: CGVer) { val both = buildList { if (mcVersion.code >= 12005) addJson("network.packet.CustomPacketPayloadMixin") addJson("CommandsMixin") @@ -85,7 +82,6 @@ fun File.processMixinsJson(mcVersion: CGVer, isFabric: Boolean) { else addJson("network.ServerConfigurationPacketListenerMixin") if (mcVersion.code < 12005) addJson("network.packet.ServerboundCustomPayloadPacketMixin") addJson("network.ServerCommonPacketListenerMixin") - if (!isFabric && mcVersion.code >= 12004) addJson("network.loader.neoforge.NetworkRegistryMixin") } val mixinsJson = JsonObject( lenientJson.decodeFromString(readText(Charsets.UTF_8)).toMutableMap().apply { diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 2720b18b..b69a8e4c 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -1,5 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import dependencies.* +import dependencies.minecraft as MC import net.fabricmc.loom.task.RemapJarTask import java.util.Locale import net.fabricmc.loom.api.LoomGradleExtensionAPI @@ -10,179 +11,191 @@ plugins { id(GradlePlugin.LegacyLoom.id) version "1.15-SNAPSHOT" apply false } -//val mcVersion = ext["mcVersion"] as CGVer -//val loaderName = "fabric" -//val projectPlugin = if (mcVersion.code >= 260100) { -// GradlePlugin.Loom -//} else { -// GradlePlugin.LegacyLoom -//} -// -//group = project.properties["maven_group"] as String -// -//apply(plugin = projectPlugin.id) -// -//loom { -// if (mcVersion.code >= 12105) { -// accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") -// } -// -// runConfigs { -// named("client") { -// runDir = "../run/client" -// configName = "Fabric Client" -// //vmArg("-Dnull2264.cobblegen.gametest=true") -// ideConfigGenerated(true) -// } -// named("server") { -// runDir = "../run/server" -// configName = "Fabric Server" -// //vmArg("-Dnull2264.cobblegen.gametest=true") -// ideConfigGenerated(true) -// } -// register("gametest") { -// server() -// name("Server GameTest") -// -// vmArg("-Dnull2264.cobblegen.gametest=true") -// vmArg("-Dfabric-api.gametest") -// vmArg("-Dfabric-api.gametest.report-file=${rootProject.layout.buildDirectory.file("reports/junit.xml").get().getAsFile()}") -// -// runDir("../run/serverGameTest") -// ideConfigGenerated(false) // Mostly for CI -// } -// } -//} -// -//tasks.withType().configureEach { -// javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) -//} -// -//fun DependencyHandlerScope.dep(configuration: String, dependency: String) { -// add( -// configuration.let { -// if (projectPlugin.isLegacy) { -// it -// } else { -// it.replace("mod", "").replaceFirstChar { c -> c.lowercase(Locale.getDefault()) } -// } -// }, -// dependency, -// ) -//} -// -//dependencies { -// val minecraft by configurations -// minecraft(MC.versioned(mcVersion)) -// if (projectPlugin.isLegacy) { -// val mappings by configurations -// mappings(loom.officialMojangMappings()) -// } -// -// dep("modImplementation", "net.fabricmc:fabric-loader:0.18.4") -// -// // Mainly for testing -// // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env -// // REF: https://github.com/FabricMC/fabric/issues/4491 -// if (mcVersion.code in 11606..12104) { -// dep("modLocalRuntime", fapi.versioned(mcVersion)) -// } else { -// try { -// // FIXME: Is Resource Loader even needed? -// //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) -// dep("modLocalRuntime", fapiGameTest.versioned(mcVersion)) -// } catch (_: IllegalStateException) { -// } -// } -// -// if (mcVersion.code >= 260100) { -// // FIXME: For some reason mixin is missing? -// dep("compileOnly", "org.spongepowered:mixin:0.8.7") -// } -// -// // Bunch of dummy classes, just so that the mod compiles -// compileOnly(project(":stubs")) -// -// if (mcVersion.code > 11605) { -// // FIXME: RuntimeOnly -// // We just want their source code so we can mixin it -// // modCompileOnly("io.github.fabricators_of_create:Porting-Lib:${project.properties["port_lib_version_1_18_2"]}") -// // modCompileOnly("com.simibubi.create:create-fabric-${project.properties["minecraft_version_1_18_2"]}:${project.properties["create_version_1_18_2"]}") -// -// // <- EMI -// if (mcVersion.code <= 11802) { -// dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(CGVer.wildcard())) -// if (project.properties["recipe_viewer"] == "emi") -// dep("modLocalRuntime", emi(mcVersion).versioned(CGVer.wildcard())) -// } else { -// if (mcVersion.code <= 12105) { -// dep("modCompileOnly", emi(mcVersion, loaderName, api = true).versioned(CGVer.wildcard())) -// if (project.properties["recipe_viewer"] == "emi") -// dep("modLocalRuntime", emi(mcVersion, loaderName).versioned(CGVer.wildcard())) -// } -// } -// // EMI -> -// -// // <- REI -// // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* -// dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) -// if (mcVersion.code in 12002..12104) { // FIXME: Not sure why it's not included -// dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") -// dep("modCompileOnly", "dev.architectury:architectury:11.1.13") -// } -// if (project.properties["recipe_viewer"] == "rei") { -// if (mcVersion.code == 11902) // REI's stupid dep bug -// dep("modLocalRuntime", "dev.architectury:architectury-fabric:6.5.77") -// dep("modLocalRuntime", rei(loaderName).versioned(mcVersion)) -// } -// // REI -> -// -// // <- JEI -// dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(CGVer.wildcard())) -// dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(CGVer.wildcard())) -// if (project.properties["recipe_viewer"] == "jei") -// dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(CGVer.wildcard())) -// // JEI -> -// -// /* FIXME: Broken, somehow -// if (mcVersion == 11802 && isFabric) { -// modLocalRuntime("com.tterrag.registrate_fabric:Registrate:MC1.18.2-1.1.7") -// modLocalRuntime("io.github.fabricators_of_create:Porting-Lib:${project.port_lib_version_1_18_2}") -// modLocalRuntime("com.simibubi.create:create-fabric-${project.minecraft_version_1_18_2}:${project.create_version_1_18_2}") -// } -// */ -// } -//} -// -//tasks.jar { -// manifest.attributes(mapOf( -// "Contains-Sources" to "java,class", -// "MixinConfigs" to "cobblegen.mixins.json", -// )) -//} -// -//if (projectPlugin.isLegacy) { -// tasks.withType { -// val shadowJar by tasks.getting(ShadowJar::class) -// inputFile.set(shadowJar.archiveFile) -// } -//} else { -// tasks.jar { -// archiveClassifier = "dev" -// } -// -// val productionJar by tasks.register("productionJar") { -// dependsOn(tasks.jar) -// archiveClassifier = "" -// archiveExtension = "jar" -// destinationDirectory = layout.buildDirectory.dir("libs") -// from(zipTree(tasks.shadowJar.flatMap { it.archiveFile })) -// } -// -// tasks.assemble { -// dependsOn(productionJar) -// } -//} +val mcVersion = ext["mcVersion"] as CGVer +val loaderName = "fabric" +val projectPlugin = if (mcVersion.code >= 260100) { + GradlePlugin.Loom +} else { + GradlePlugin.LegacyLoom +} + +group = project.properties["maven_group"] as String + +apply(plugin = projectPlugin.id) + +fun GradlePlugin.configure(configuration: LoomGradleExtensionAPI.() -> Unit = {}) = + project.the() + .apply { + if (mcVersion.code >= 12105) { + accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") + } + + runConfigs { + named("client") { + runDir = "../run/client" + configName = "Fabric Client" + //vmArg("-Dnull2264.cobblegen.gametest=true") + ideConfigGenerated(true) + } + named("server") { + runDir = "../run/server" + configName = "Fabric Server" + //vmArg("-Dnull2264.cobblegen.gametest=true") + ideConfigGenerated(true) + } + register("gametest") { + server() + name("Server GameTest") + + vmArg("-Dnull2264.cobblegen.gametest=true") + vmArg("-Dfabric-api.gametest") + vmArg( + "-Dfabric-api.gametest.report-file=${ + rootProject.layout.buildDirectory.file("reports/junit.xml").get().getAsFile() + }" + ) + + runDir("../run/serverGameTest") + ideConfigGenerated(false) // Mostly for CI + } + } + + configuration() + } + +val loom = projectPlugin.configure() + +//if (projectPlugin.isLegacy) loom.silentMojangMappingsLicense() + +tasks.withType().configureEach { + javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) +} + +fun DependencyHandlerScope.dep(configuration: String, dependency: String) { + add( + configuration.let { + if (projectPlugin.isLegacy) { + it + } else { + it.replace("mod", "").replaceFirstChar { c -> c.lowercase(Locale.getDefault()) } + } + }, + dependency, + ) +} + +dependencies { + val minecraft by configurations + minecraft(MC.versioned(mcVersion)) + if (projectPlugin.isLegacy) { + val mappings by configurations + mappings(loom.officialMojangMappings()) + } + + dep("modImplementation", "net.fabricmc:fabric-loader:0.18.4") + + // Mainly for testing + // Only use gametest API for 1.21.5+, because the full FAPI is causing crashes on dev env + // REF: https://github.com/FabricMC/fabric/issues/4491 + if (mcVersion.code in 11606..12104) { + dep("modLocalRuntime", fapi.versioned(mcVersion)) + } else { + try { + // FIXME: Is Resource Loader even needed? + //modLocalRuntime(fapiResourceLoader.versioned(mcVersion)) + dep("modLocalRuntime", fapiGameTest.versioned(mcVersion)) + } catch (_: IllegalStateException) { + } + } + + if (mcVersion.code >= 260100) { + // FIXME: For some reason mixin is missing? + dep("compileOnly", "org.spongepowered:mixin:0.8.7") + } + + // Bunch of dummy classes, just so that the mod compiles + compileOnly(project(":stubs")) + + if (mcVersion.code > 11605) { + // FIXME: RuntimeOnly + // We just want their source code so we can mixin it + // modCompileOnly("io.github.fabricators_of_create:Porting-Lib:${project.properties["port_lib_version_1_18_2"]}") + // modCompileOnly("com.simibubi.create:create-fabric-${project.properties["minecraft_version_1_18_2"]}:${project.properties["create_version_1_18_2"]}") + + // <- EMI + if (mcVersion.code <= 11802) { + dep("modCompileOnly", emi(mcVersion, null, api = true).versioned(CGVer.wildcard())) + if (project.properties["recipe_viewer"] == "emi") + dep("modLocalRuntime", emi(mcVersion).versioned(CGVer.wildcard())) + } else { + if (mcVersion.code <= 12105) { + dep("modCompileOnly", emi(mcVersion, loaderName, api = true).versioned(CGVer.wildcard())) + if (project.properties["recipe_viewer"] == "emi") + dep("modLocalRuntime", emi(mcVersion, loaderName).versioned(CGVer.wildcard())) + } + } + // EMI -> + + // <- REI + // Use the full package instead of 'api-' for (neo)forge, since the 'api-' didn't include @REIPlugin* + dep("modCompileOnly", rei(loaderName, true).versioned(mcVersion)) + if (mcVersion.code in 12002..12104) { // FIXME: Not sure why it's not included + dep("modCompileOnly", "me.shedaniel.cloth:basic-math:0.6.1") + dep("modCompileOnly", "dev.architectury:architectury:11.1.13") + } + if (project.properties["recipe_viewer"] == "rei") { + if (mcVersion.code == 11902) // REI's stupid dep bug + dep("modLocalRuntime", "dev.architectury:architectury-fabric:6.5.77") + dep("modLocalRuntime", rei(loaderName).versioned(mcVersion)) + } + // REI -> + + // <- JEI + dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(CGVer.wildcard())) + dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(CGVer.wildcard())) + if (project.properties["recipe_viewer"] == "jei") + dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(CGVer.wildcard())) + // JEI -> + + /* FIXME: Broken, somehow + if (mcVersion == 11802 && isFabric) { + modLocalRuntime("com.tterrag.registrate_fabric:Registrate:MC1.18.2-1.1.7") + modLocalRuntime("io.github.fabricators_of_create:Porting-Lib:${project.port_lib_version_1_18_2}") + modLocalRuntime("com.simibubi.create:create-fabric-${project.minecraft_version_1_18_2}:${project.create_version_1_18_2}") + } + */ + } +} + +tasks.jar { + manifest.attributes(mapOf( + "Contains-Sources" to "java,class", + "MixinConfigs" to "cobblegen.mixins.json", + )) +} + +if (projectPlugin.isLegacy) { + tasks.withType { + val shadowJar by tasks.getting(ShadowJar::class) + inputFile.set(shadowJar.archiveFile) + } +} else { + tasks.jar { + archiveClassifier = "dev" + } + + val productionJar by tasks.register("productionJar") { + dependsOn(tasks.jar) + archiveClassifier = "" + archiveExtension = "jar" + destinationDirectory = layout.buildDirectory.dir("libs") + from(zipTree(tasks.shadowJar.flatMap { it.archiveFile })) + } + + tasks.assemble { + dependsOn(productionJar) + } +} //val deleteResources by tasks.creating(Delete::class) { // delete(file("build/resources/main")) diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 52eb0982..4bf633be 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -27,23 +27,23 @@ group = project.properties["maven_group"] as String apply(plugin = projectPlugin.id) -inline fun GradlePlugin.configureNeo(configuration: T.() -> Unit = {}) { +inline fun GradlePlugin.configure(configuration: T.() -> Unit = {}) { project.the() .apply { // FIXME: AccessWidener to AccessTransformer validateAccessTransformers = mcVersion.code >= 12105 runs { - create("client") { - client() - gameDirectory.set(rootProject.file("run/client")) - ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") - } - create("server") { - server() - gameDirectory.set(rootProject.file("run/server")) - ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") - } +// create("client") { +// client() +// gameDirectory.set(rootProject.file("run/client")) +// ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") +// } +// create("server") { +// server() +// gameDirectory.set(rootProject.file("run/server")) +// ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") +// } create("gametest") { type = "gameTestServer" gameDirectory.set(rootProject.file("run/serverGameTest")) @@ -74,9 +74,9 @@ inline fun GradlePlugin.configureNeo(configuration: } } -if (projectPlugin.isLegacy) projectPlugin.configureNeo { +if (projectPlugin.isLegacy) projectPlugin.configure { version = lexForge.version(mcVersion) -} else projectPlugin.configureNeo { +} else projectPlugin.configure { version = NEO.version(mcVersion) } From efe8ac202654aae409bdce3b9da2443c79bd74b9 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sun, 1 Feb 2026 10:36:07 +0700 Subject: [PATCH 86/92] refactor: WIP split 3 Finally fix the gradle sync --- build.gradle.kts | 36 ++++++++++++++++++------------------ fabric/build.gradle.kts | 4 ++-- forge/build.gradle.kts | 7 ++++--- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index cd2fcebd..d2a3f841 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,8 @@ import org.apache.tools.ant.filters.StripJavaComments plugins { id("java") - id("architectury-plugin") version "3.4-SNAPSHOT" apply false + // Explicitly add idea-ext here since without it being here :stubs and :fabric would both try to apply it at the same time causing error + id("org.jetbrains.gradle.plugin.idea-ext") version "1.3" apply false id("com.gradleup.shadow") apply false id("me.modmuss50.mod-publish-plugin") version "1.1.0" } @@ -21,22 +22,22 @@ val versionRange = supportedVersionRange(mcVersion, loaderName) /** * We're using LegacyMDG instead of ForgeGradle because they provide similar API to Loom instead of the atrocious "fg.deobf" */ -val projectPlugin = when { - // LegacyMDG only support 1.17 up to 1.20.1 - mcVersion.code <= 11605 -> GradlePlugin.ArchLoom - isNeo -> when { - mcVersion.code <= 12001 -> GradlePlugin.LegacyMDG - // 1.20.2+ is in some kind of limbo for whatever reason, not supported by MDG and not supported by LegacyMDG. - mcVersion.code in 12002..12006 -> GradlePlugin.ArchLoom - else -> GradlePlugin.MDG - } - isForge -> { - assert(mcVersion.code <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } - GradlePlugin.LegacyMDG - } - isFabric -> if (mcVersion.code <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom - else -> throw IllegalStateException() -} +//val projectPlugin = when { +// // LegacyMDG only support 1.17 up to 1.20.1 +// mcVersion.code <= 11605 -> GradlePlugin.ArchLoom +// isNeo -> when { +// mcVersion.code <= 12001 -> GradlePlugin.LegacyMDG +// // 1.20.2+ is in some kind of limbo for whatever reason, not supported by MDG and not supported by LegacyMDG. +// mcVersion.code in 12002..12006 -> GradlePlugin.ArchLoom +// else -> GradlePlugin.MDG +// } +// isForge -> { +// assert(mcVersion.code <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } +// GradlePlugin.LegacyMDG +// } +// isFabric -> if (mcVersion.code <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom +// else -> throw IllegalStateException() +//} fun setupPreprocessor() { val buildProps = buildString { @@ -60,7 +61,6 @@ allprojects { extra["isFabric"] = isFabric extra["isForge"] = isForge extra["isNeo"] = isNeo - extra["projectPlugin"] = projectPlugin base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index b69a8e4c..578e0c57 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -7,8 +7,8 @@ import net.fabricmc.loom.api.LoomGradleExtensionAPI plugins { id("multiloader") - id(GradlePlugin.Loom.id) version "1.15-SNAPSHOT" apply false - id(GradlePlugin.LegacyLoom.id) version "1.15-SNAPSHOT" apply false + id(GradlePlugin.Loom.id) version "1.14.10" apply false + id(GradlePlugin.LegacyLoom.id) version "1.14.10" apply false } val mcVersion = ext["mcVersion"] as CGVer diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 4bf633be..e62fc46a 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -7,6 +7,7 @@ import net.neoforged.moddevgradle.legacyforge.dsl.LegacyForgeExtension import net.neoforged.moddevgradle.legacyforge.dsl.MixinExtension import net.neoforged.moddevgradle.legacyforge.dsl.ObfuscationExtension import net.neoforged.moddevgradle.tasks.JarJar +import org.gradle.kotlin.dsl.configureEach plugins { id("multiloader") @@ -34,6 +35,9 @@ inline fun GradlePlugin.configure(configuration: T. validateAccessTransformers = mcVersion.code >= 12105 runs { +// configureEach { +// javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) +// } // create("client") { // client() // gameDirectory.set(rootProject.file("run/client")) @@ -80,9 +84,6 @@ if (projectPlugin.isLegacy) projectPlugin.configure { version = NEO.version(mcVersion) } -tasks.withType().configureEach { - javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) -} fun DependencyHandlerScope.dep(configuration: String, dependency: String) { add( From 62db445d4149da8d278ce0117b83a3d90f14d159 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sun, 1 Feb 2026 14:15:42 +0700 Subject: [PATCH 87/92] refactor: WIP split 4 --- build.gradle.kts | 47 +++------- .../src/main/kotlin/ProcessModMetadata.kt | 9 +- .../src/main/kotlin/multiloader.gradle.kts | 24 ++--- .../cobblegen/fabric/CobbleGenFabric.java | 7 ++ .../fabric/compat/LoaderCompatFabric.java | 36 ++++++++ .../CreateFluidReactionsMixin$PatchE.java | 37 ++++++++ .../fabric/util/PluginFinderFabric.java | 22 +++++ forge/build.gradle.kts | 22 ++--- .../cobblegen/forge/CobbleGenForge.java | 14 +-- .../forge/compat/LoaderCompatForge.java | 40 +++++++++ .../CreateFluidReactionsMixin$PatchE.java | 18 ++-- .../forge/util/PluginFinderForge.java | 76 ++++++++++++++++ xplat/build.gradle.kts | 8 +- .../cobblegen/compat/LoaderCompat.java | 87 +++++-------------- .../null2264/cobblegen/util/PluginFinder.java | 86 +++--------------- 15 files changed, 312 insertions(+), 221 deletions(-) create mode 100644 fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java create mode 100644 fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/create/CreateFluidReactionsMixin$PatchE.java create mode 100644 fabric/src/main/java/io/github/null2264/cobblegen/fabric/util/PluginFinderFabric.java create mode 100644 forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java rename {xplat/src/main/java/io/github/null2264/cobblegen => forge/src/main/java/io/github/null2264/cobblegen/forge}/mixin/create/CreateFluidReactionsMixin$PatchE.java (87%) create mode 100644 forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java diff --git a/build.gradle.kts b/build.gradle.kts index d2a3f841..30b234a9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,39 +12,14 @@ plugins { val modVersion = System.getenv("VERSION") ?: project.properties["mod_version"] as? String ?: "0.0.0" val loaderName = project.properties["null2264.platform"] as? String ?: "" -val isForge = loaderName.endsWith("forge") -val isNeo = loaderName.endsWith("neoforge") -val isFabric = loaderName.endsWith("fabric") val mcVersionStr = project.properties["mcVer"] as? String ?: "" val mcVersion = CGVer.fromString(mcVersionStr) val versionRange = supportedVersionRange(mcVersion, loaderName) -/** - * We're using LegacyMDG instead of ForgeGradle because they provide similar API to Loom instead of the atrocious "fg.deobf" - */ -//val projectPlugin = when { -// // LegacyMDG only support 1.17 up to 1.20.1 -// mcVersion.code <= 11605 -> GradlePlugin.ArchLoom -// isNeo -> when { -// mcVersion.code <= 12001 -> GradlePlugin.LegacyMDG -// // 1.20.2+ is in some kind of limbo for whatever reason, not supported by MDG and not supported by LegacyMDG. -// mcVersion.code in 12002..12006 -> GradlePlugin.ArchLoom -// else -> GradlePlugin.MDG -// } -// isForge -> { -// assert(mcVersion.code <= 12001) { "Forge support ends at 1.20.1, the rest will be Neo-only" } -// GradlePlugin.LegacyMDG -// } -// isFabric -> if (mcVersion.code <= 12111) GradlePlugin.LegacyLoom else GradlePlugin.Loom -// else -> throw IllegalStateException() -//} - fun setupPreprocessor() { val buildProps = buildString { append("# DON'T TOUCH THIS FILE, This is handled by the build script\n") append("MC=${mcVersion.code}\n") - if (isFabric) append("FABRIC=1\n") - if (isForge) append("FORGE=${if (!isNeo) "1" else "2"}\n") } project.file("build.properties").writeText(buildProps) @@ -58,9 +33,8 @@ allprojects { extra["mcVersion"] = mcVersion extra["mcVersionStr"] = mcVersionStr extra["loaderName"] = loaderName - extra["isFabric"] = isFabric - extra["isForge"] = isForge - extra["isNeo"] = isNeo + val isFabric = project == project(":fabric") + val isNeo = !isFabric && mcVersion.code >= 12002 base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") @@ -127,6 +101,9 @@ subprojects { // NOTE: This here for when I finally split the API to its own module, hopefully on v6.0 val isApi = false; // APIs shouldn't contain anything Minecraft related val isModModule = project in listOf(project(":fabric"), project(":forge")) + val isFabric = project == project(":fabric") + val isForge = project == project(":forge") + val isNeo = isForge && mcVersion.code >= 12002 apply(plugin = "java") apply(plugin = "com.gradleup.shadow") @@ -197,20 +174,20 @@ subprojects { if (!isModModule) return@withType val metadataVersion = "${modVersion}-${project.properties["version_stage"]}" - val metadataMCVersion = if (project == project(":forge")) versionRange.mavenStyle() else versionRange.semverStyle() + val metadataMCVersion = if (isForge) versionRange.mavenStyle() else versionRange.semverStyle() val properties = mapOf( "version" to metadataVersion, "mcversion" to metadataMCVersion, - "forge" to (if (mcVersion.code >= 12002) "neoforge" else "forge"), + "forge" to (if (isNeo) "neoforge" else "forge"), ) inputs.properties(properties) filteringCharset = Charsets.UTF_8.name() val metadataFilename = - if (project == project(":fabric")) { + if (isFabric) { "fabric.mod.json" } else { - if (mcVersion.code >= 12006) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml" + if (isNeo && mcVersion.code >= 12006) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml" } filesMatching(metadataFilename) { @@ -225,7 +202,7 @@ subprojects { doLast { // For some reason Mojang rename the structure directory on MC 1.21 to singular form val structureDirName = if (mcVersion.code >= 12100) "structure" else "structures" - if (project == project(":fabric") || mcVersion.code >= 12105) { + if (isFabric || mcVersion.code >= 12105) { project.file("build/resources/main/data/cobblegen/gametest/${structureDirName}/").mkdirs() project.file("build/resources/main/data/cobblegen/gametest/${structureDirName}/empty.snbt") .writeStructureAsSnbt(generateStructure(false)) @@ -239,10 +216,10 @@ subprojects { // We can't preprocess resources files with Manifold, so we'll construct the json files manually here instead. project(":common").file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion) project.file("build/resources/main/cobblegen.${project.name}.mixins.json").apply { - if (project == project(":fabric")) processMixinsJsonFabric(mcVersion) + if (isFabric) processMixinsJsonFabric(mcVersion) else processMixinsJsonForge(mcVersion) } - if (project == project(":fabric")) project.file("build/resources/main/fabric.mod.json").processFabricModJson(mcVersion) + if (isFabric) project.file("build/resources/main/fabric.mod.json").processFabricModJson(mcVersion) else project.file("build/resources/main/$metadataFilename").processModsToml(mcVersion, if (mcVersion.code >= 12002) 2 else 1) } } diff --git a/buildSrc/src/main/kotlin/ProcessModMetadata.kt b/buildSrc/src/main/kotlin/ProcessModMetadata.kt index 059fb3bf..0f38c437 100644 --- a/buildSrc/src/main/kotlin/ProcessModMetadata.kt +++ b/buildSrc/src/main/kotlin/ProcessModMetadata.kt @@ -27,6 +27,7 @@ fun File.processModsToml( fun File.processMixinsJsonFabric(mcVersion: CGVer) { val both = buildList { if (mcVersion.code > 11605) { + addJson("create.CreateFluidReactionsMixin\$PatchE") addJson("create.CreateFluidReactionsMixin\$PatchF") } } @@ -41,13 +42,18 @@ fun File.processMixinsJsonFabric(mcVersion: CGVer) { } fun File.processMixinsJsonForge(mcVersion: CGVer) { + val both = buildList { + if (mcVersion.code > 11605) { + addJson("create.CreateFluidReactionsMixin\$PatchE") + } + } val server = buildList { if (mcVersion.code >= 12004) addJson("network.loader.neoforge.NetworkRegistryMixin") } val mixinsJson = JsonObject( lenientJson.decodeFromString(readText(Charsets.UTF_8)).toMutableMap().apply { set("compatibilityLevel", JsonPrimitive(if (mcVersion.code <= 11605) "JAVA_8" else "JAVA_17")) - set("mixins", JsonArray(listOf())) + set("mixins", JsonArray(both)) set("client", JsonArray(listOf())) set("server", JsonArray(server)) } @@ -61,7 +67,6 @@ fun File.processMixinsJson(mcVersion: CGVer) { addJson("MinecraftServerMixin") if (mcVersion.code > 11605) { addJson("create.CreateFluidReactionsMixin\$OFive") - addJson("create.CreateFluidReactionsMixin\$PatchE") } addJson("fluid.FlowingFluidEventMixin") addJson("fluid.FluidEventMixin") diff --git a/buildSrc/src/main/kotlin/multiloader.gradle.kts b/buildSrc/src/main/kotlin/multiloader.gradle.kts index 80d9b2c8..0878fd82 100644 --- a/buildSrc/src/main/kotlin/multiloader.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader.gradle.kts @@ -2,32 +2,32 @@ plugins { id("java-library") } -val commonJava by configurations.creating { +val xplatJava by configurations.creating { isCanBeResolved = true } -val commonResources by configurations.creating { +val xplatResources by configurations.creating { isCanBeResolved = true } dependencies { compileOnly(project(":xplat")) - commonJava(project(":xplat", "commonJava")) - commonResources(project(":xplat", "commonResources")) + xplatJava(project(":xplat", "xplatJava")) + xplatResources(project(":xplat", "xplatResources")) } tasks.compileJava { - dependsOn(commonJava) - source(commonJava) + dependsOn(xplatJava) + source(xplatJava) } tasks.named("sourcesJar") { - dependsOn(commonJava) - dependsOn(commonResources) - from(commonJava) - from(commonResources) + dependsOn(xplatJava) + dependsOn(xplatResources) + from(xplatJava) + from(xplatResources) } tasks.processResources { - dependsOn(commonResources) - from(commonResources) + dependsOn(xplatResources) + from(xplatResources) } diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java index 9e15f08e..a15c1cee 100644 --- a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java @@ -1,10 +1,17 @@ package io.github.null2264.cobblegen.fabric; import io.github.null2264.cobblegen.CobbleGen; +import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.fabric.util.PluginFinderFabric; +import io.github.null2264.cobblegen.forge.compat.LoaderCompatFabric; +import io.github.null2264.cobblegen.util.PluginFinder; public class CobbleGenFabric extends CobbleGen implements net.fabricmc.api.ModInitializer { + @Override public void onInitialize() { + LoaderCompat.init(new LoaderCompatFabric()); + PluginFinder.init(new PluginFinderFabric()); super.init(); } } diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java new file mode 100644 index 00000000..a9512e2e --- /dev/null +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java @@ -0,0 +1,36 @@ +package io.github.null2264.cobblegen.forge.compat; + +import io.github.null2264.cobblegen.compat.LoaderCompat; + +import java.nio.file.Path; + +public class LoaderCompatFabric extends LoaderCompat { + + @Override + public boolean isModLoaded(String mod) { + return net.fabricmc.loader.api.FabricLoader.getInstance().isModLoaded(mod); + } + + @Override + public Path getConfigDir() { + #if MC>11605 + return FabricLoader.getInstance().getConfigDir(); + #else + // Not ideal, but configDir is null somehow in 1.16.5 + Path configDir = FileSystems.getDefault().getPath(".", "config"); + if (!Files.exists(configDir)) { // Stolen from fabric loader + try { + Files.createDirectories(configDir); + } catch (IOException e) { + throw new RuntimeException("Creating config directory", e); + } + } + return configDir; + #endif + } + + @Override + public LoaderType getType() { + return LoaderType.FABRIC; + } +} diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/create/CreateFluidReactionsMixin$PatchE.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/create/CreateFluidReactionsMixin$PatchE.java new file mode 100644 index 00000000..3660eae3 --- /dev/null +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/create/CreateFluidReactionsMixin$PatchE.java @@ -0,0 +1,37 @@ +#if MC>11605 +package io.github.null2264.cobblegen.fabric.mixin.create; + +import io.github.fabricators_of_create.porting_lib.util.FluidStack; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static io.github.null2264.cobblegen.CobbleGen.FLUID_INTERACTION; + +/** + * Mixin for Create Fabric (pre) Patch F + */ +@Pseudo +@Mixin(targets = {"com.simibubi.create.content.contraptions.fluids.FluidReactions", "com.simibubi.create.content.fluids.FluidReactions"}) +public abstract class CreateFluidReactionsMixin$PatchE +{ + @Inject( + method = "handlePipeFlowCollision", + #if FORGE + remap = false, + #endif + at = @At(value = "HEAD"), cancellable = true + ) + private static void generator$handlePipeFlowCollision( + Level level, BlockPos pos, FluidStack fluid1, FluidStack fluid2, CallbackInfo ci + ) { + final boolean success = FLUID_INTERACTION.interactFromPipe(level, pos, fluid1.getFluid(), fluid2.getFluid()); + if (success) + ci.cancel(); + } +} +#endif diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/util/PluginFinderFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/util/PluginFinderFabric.java new file mode 100644 index 00000000..786f03a8 --- /dev/null +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/util/PluginFinderFabric.java @@ -0,0 +1,22 @@ +package io.github.null2264.cobblegen.fabric.util; + +import io.github.null2264.cobblegen.CobbleGenPlugin; +import io.github.null2264.cobblegen.util.PluginFinder; +import net.fabricmc.loader.api.FabricLoader; + +import java.util.List; + +import static io.github.null2264.cobblegen.compat.CollectionCompat.streamToList; + +public class PluginFinderFabric extends PluginFinder { + + @Override + public List getModPlugins() { + return streamToList( + FabricLoader.getInstance() + .getEntrypointContainers("cobblegen_plugin", CobbleGenPlugin.class) + .stream() + .map(entrypoint -> new PlugInContainer(entrypoint.getProvider().getMetadata().getId(), entrypoint.getEntrypoint())) + ); + } +} diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index e62fc46a..1b019031 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -16,8 +16,8 @@ plugins { } val mcVersion = ext["mcVersion"] as CGVer -val loaderName = ext["loaderName"] as String val isNeo = mcVersion.code >= 12002 +val loaderName = if (isNeo) "neoforge" else "forge" val projectPlugin = if (mcVersion.code >= 12002) { GradlePlugin.MDG } else { @@ -38,16 +38,16 @@ inline fun GradlePlugin.configure(configuration: T. // configureEach { // javaLauncher.set(javaToolchains.launcherFor(java.toolchain)) // } -// create("client") { -// client() -// gameDirectory.set(rootProject.file("run/client")) -// ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") -// } -// create("server") { -// server() -// gameDirectory.set(rootProject.file("run/server")) -// ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") -// } + create("client") { + client() + gameDirectory.set(rootProject.file("run/client")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Client") + } + create("server") { + server() + gameDirectory.set(rootProject.file("run/server")) + ideName.set((if (!isNeo) "Forge" else "NeoForge") + " Server") + } create("gametest") { type = "gameTestServer" gameDirectory.set(rootProject.file("run/serverGameTest")) diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java index 5edf5aaa..5bfca4ba 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java @@ -1,17 +1,21 @@ package io.github.null2264.cobblegen.fabric; import io.github.null2264.cobblegen.CobbleGen; +import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.forge.compat.LoaderCompatForge; +import io.github.null2264.cobblegen.forge.util.PluginFinderForge; +import io.github.null2264.cobblegen.util.PluginFinder; -#if FORGE - #if FORGE==2 +#if MC>=12002 @net.neoforged.fml.common.Mod(CobbleGen.MOD_ID) - #elif FORGE==1 +#else @net.minecraftforge.fml.common.Mod(CobbleGen.MOD_ID) - #endif #endif public class CobbleGenForge extends CobbleGen { - public CobbleGenForge { + public CobbleGenForge() { + LoaderCompat.init(new LoaderCompatForge()); + PluginFinder.init(new PluginFinderForge()); #if MC>=11801 && MC<12105 // I was gonna do RegisterGameTestsEvent like a normal person, but there's a check that I need to bypass otherwise Forge won't register my test net.minecraft.gametest.framework.GameTestRegistry.register(io.github.null2264.cobblegen.gametest.BlockGenerationTest.class); diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java new file mode 100644 index 00000000..90c7b683 --- /dev/null +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java @@ -0,0 +1,40 @@ +package io.github.null2264.cobblegen.forge.compat; + +import io.github.null2264.cobblegen.compat.LoaderCompat; + +import java.nio.file.Path; + +#if MC>=12002 +import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.LoadingModList; +#else +import net.minecraftforge.fml.loading.FMLPaths; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.loading.LoadingModList; +#endif + +public class LoaderCompatForge extends LoaderCompat { + + @Override + public boolean isModLoaded(String mod) { + ModList modlist = ModList.get(); + if (modlist == null) // mainly for MixinConfigPlugin + return LoadingModList.get().getModFileById(mod) != null; + return modlist.isLoaded(mod); + } + + @Override + public Path getConfigDir() { + return FMLPaths.CONFIGDIR.get(); + } + + @Override + public LoaderType getType() { + #if MC>=12002 + return LoaderType.NEOFORGE; + #else + return LoaderType.FORGE; + #endif + } +} diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/create/CreateFluidReactionsMixin$PatchE.java similarity index 87% rename from xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java rename to forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/create/CreateFluidReactionsMixin$PatchE.java index 745d57e9..f850f0ab 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/mixin/create/CreateFluidReactionsMixin$PatchE.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/create/CreateFluidReactionsMixin$PatchE.java @@ -1,15 +1,5 @@ #if MC>11605 -package io.github.null2264.cobblegen.mixin.create; - -#if FABRIC -import io.github.fabricators_of_create.porting_lib.util.FluidStack; -#else - #if FORGE>=2 && MC>=12002 -import net.neoforged.neoforge.fluids.FluidStack; - #else -import net.minecraftforge.fluids.FluidStack; - #endif -#endif +package io.github.null2264.cobblegen.forge.mixin.create; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; @@ -21,6 +11,12 @@ import static io.github.null2264.cobblegen.CobbleGen.FLUID_INTERACTION; +#if MC>=12002 +import net.neoforged.neoforge.fluids.FluidStack; +#else +import net.minecraftforge.fluids.FluidStack; +#endif + /** * Mixin for Create Fabric (pre) Patch F */ diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java new file mode 100644 index 00000000..b48bc35b --- /dev/null +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java @@ -0,0 +1,76 @@ +package io.github.null2264.cobblegen.forge.util; + +import io.github.null2264.cobblegen.CGPlugin; +import io.github.null2264.cobblegen.CobbleGenPlugin; +import io.github.null2264.cobblegen.util.PluginFinder; +import java.lang.reflect.Constructor; +import org.objectweb.asm.Type; + +import java.util.ArrayList; +import java.util.List; + +import static io.github.null2264.cobblegen.compat.CollectionCompat.streamToList; + +#if MC>=12002 +import net.neoforged.fml.ModList; +import net.neoforged.neoforgespi.language.IModInfo; +import net.neoforged.neoforgespi.language.ModFileScanData; +#else +import net.minecraftforge.fml.ModList; +import net.minecraftforge.forgespi.language.IModInfo; +import net.minecraftforge.forgespi.language.ModFileScanData; +#endif + +public class PluginFinderForge extends PluginFinder { + + @Override + public List getModPlugins() { + return AnnotatedFinder.getInstances(CGPlugin.class, CobbleGenPlugin.class); + } + + static class AnnotatedFinder { + public static List getInstances(Class annotationClass, Class instanceClass) { + Type annotationType = Type.getType(annotationClass); + List allScanData = ModList.get().getAllScanData(); + List instances = new ArrayList<>(); + for (ModFileScanData data : allScanData) { + List modIds = streamToList( + data.getIModInfoData().stream() + .flatMap(info -> info.getMods().stream()) + .map(IModInfo::getModId) + ); + String modId = "[" + String.join(", ", modIds) + "]"; + + Iterable annotations = data.getAnnotations(); + for (ModFileScanData.AnnotationData a : annotations) { + + if (!(Objects.equals( + #if MC>11605 + a.annotationType(), + #else + a.getAnnotationType(), + #endif + annotationType))) + continue; + + String className = + #if MC>11605 + a.memberName(); + #else + a.getMemberName(); + #endif + try { + Class asmClass = Class.forName(className); + Class asmInstanceClass = asmClass.asSubclass(instanceClass); + Constructor constructor = asmInstanceClass.getDeclaredConstructor(); + T instance = constructor.newInstance(); + instances.add(new PlugInContainer(modId, (CobbleGenPlugin) instance)); + } catch (Throwable t) { + CGLog.error("Failed to load: " + className + " ", t); + } + } + } + return instances; + } + } +} diff --git a/xplat/build.gradle.kts b/xplat/build.gradle.kts index 1b08a531..4d4f29a0 100644 --- a/xplat/build.gradle.kts +++ b/xplat/build.gradle.kts @@ -14,11 +14,11 @@ repositories { } configurations { - register("commonJava") { + register("xplatJava") { isCanBeResolved = false isCanBeConsumed = true } - register("commonResources") { + register("xplatResources") { isCanBeResolved = false isCanBeConsumed = true } @@ -30,8 +30,8 @@ dependencies { } artifacts { - add("commonJava", sourceSets.main.get().java.sourceDirectories.singleFile) - add("commonResources", sourceSets.main.get().resources.sourceDirectories.singleFile) + add("xplatJava", sourceSets.main.get().java.sourceDirectories.singleFile) + add("xplatResources", sourceSets.main.get().resources.sourceDirectories.singleFile) } publishing { diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java index 7a7ff50c..227269dd 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java @@ -9,94 +9,49 @@ import java.nio.file.FileSystems; import java.nio.file.Files; #endif -#elif FORGE - #if FORGE>=2 && MC>=12002 -import net.neoforged.fml.loading.FMLPaths; -import net.neoforged.fml.ModList; -import net.neoforged.fml.loading.LoadingModList; - #else -import net.minecraftforge.fml.loading.FMLPaths; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.loading.LoadingModList; - #endif -#else - #error "Invalid loader name" #endif -public class LoaderCompat { - public static boolean isModLoaded(String mod) { - #if FABRIC - return net.fabricmc.loader.api.FabricLoader.getInstance().isModLoaded(mod); - #else - ModList modlist = ModList.get(); - if (modlist == null) // mainly for MixinConfigPlugin - return LoadingModList.get().getModFileById(mod) != null; - return modlist.isLoaded(mod); - #endif - } +public abstract class LoaderCompat { + + private static LoaderCompat INSTANCE; - public static Path getConfigDir() { - #if FABRIC - #if MC>11605 - return FabricLoader.getInstance().getConfigDir(); - #else - // Not ideal, but configDir is null somehow in 1.16.5 - Path configDir = FileSystems.getDefault().getPath(".", "config"); - if (!Files.exists(configDir)) { // Stolen from fabric loader - try { - Files.createDirectories(configDir); - } catch (IOException e) { - throw new RuntimeException("Creating config directory", e); - } - } - return configDir; - #endif - #elif FORGE - return FMLPaths.CONFIGDIR.get(); - #else - #error "Invalid loader name" - #endif + public static void init(LoaderCompat impl) { + if (INSTANCE != null) throw new IllegalStateException("Already initialized!"); + INSTANCE = impl; } - public static LoaderType getType() { - #if FABRIC - #if FABRIC==1 - return LoaderType.FABRIC; - #else - return LoaderType.QUILT; - #endif - #elif FORGE - #if FORGE==1 - return LoaderType.FORGE; - #else - return LoaderType.NEOFORGE; - #endif - #else - #error "Invalid loader name" - #endif + public static LoaderCompat getInstance() { + if (INSTANCE == null) throw new IllegalStateException("Not yet initialized!"); + return INSTANCE; } - public static Boolean isFabric() { + public abstract boolean isModLoaded(String mod); + + public abstract Path getConfigDir(); + + public abstract LoaderType getType(); + + public Boolean isFabric() { return getType() == LoaderType.FABRIC; } - public static Boolean isQuilt() { + public Boolean isQuilt() { return getType() == LoaderType.QUILT; } - public static Boolean isFabricLike() { + public Boolean isFabricLike() { return isFabric() || isQuilt(); } - public static Boolean isForge() { + public Boolean isForge() { return getType() == LoaderType.FORGE; } - public static Boolean isNeoForge() { + public Boolean isNeoForge() { return getType() == LoaderType.NEOFORGE; } - public static Boolean isForgeLike() { + public Boolean isForgeLike() { return isForge() || isNeoForge(); } diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java index 205e3114..4dcf4bf8 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/util/PluginFinder.java @@ -7,85 +7,21 @@ import static io.github.null2264.cobblegen.compat.CollectionCompat.streamToList; -#if FABRIC -import net.fabricmc.loader.api.FabricLoader; -#else -import java.lang.reflect.Constructor; -import io.github.null2264.cobblegen.CGPlugin; - #if FORGE>=2 && MC>=12002 -import net.neoforged.fml.ModList; -import net.neoforged.neoforgespi.language.IModInfo; -import net.neoforged.neoforgespi.language.ModFileScanData; - #else -import net.minecraftforge.fml.ModList; -import net.minecraftforge.forgespi.language.IModInfo; -import net.minecraftforge.forgespi.language.ModFileScanData; - #endif -import org.objectweb.asm.Type; -#endif +public abstract class PluginFinder { -public class PluginFinder -{ - public static List getModPlugins() { - #if FABRIC - return streamToList( - FabricLoader.getInstance() - .getEntrypointContainers("cobblegen_plugin", CobbleGenPlugin.class) - .stream() - .map(entrypoint -> new PlugInContainer(entrypoint.getProvider().getMetadata().getId(), entrypoint.getEntrypoint())) - ); - #else - return AnnotatedFinder.getInstances(CGPlugin.class, CobbleGenPlugin.class); - #endif - } - - #if FORGE - static class AnnotatedFinder { - public static List getInstances(Class annotationClass, Class instanceClass) { - Type annotationType = Type.getType(annotationClass); - List allScanData = ModList.get().getAllScanData(); - List instances = new ArrayList<>(); - for (ModFileScanData data : allScanData) { - List modIds = streamToList( - data.getIModInfoData().stream() - .flatMap(info -> info.getMods().stream()) - .map(IModInfo::getModId) - ); - String modId = "[" + String.join(", ", modIds) + "]"; - - Iterable annotations = data.getAnnotations(); - for (ModFileScanData.AnnotationData a : annotations) { + private static PluginFinder INSTANCE; - if (!(Objects.equals( - #if MC>11605 - a.annotationType(), - #else - a.getAnnotationType(), - #endif - annotationType))) - continue; + public static void init(PluginFinder impl) { + if (INSTANCE != null) throw new IllegalStateException("Already initialized!"); + INSTANCE = impl; + } - String className = - #if MC>11605 - a.memberName(); - #else - a.getMemberName(); - #endif - try { - Class asmClass = Class.forName(className); - Class asmInstanceClass = asmClass.asSubclass(instanceClass); - Constructor constructor = asmInstanceClass.getDeclaredConstructor(); - T instance = constructor.newInstance(); - instances.add(new PlugInContainer(modId, (CobbleGenPlugin) instance)); - } catch (Throwable t) { - CGLog.error("Failed to load: " + className + " ", t); - } - } - } - return instances; - } + public static PluginFinder getInstance() { + if (INSTANCE == null) throw new IllegalStateException("Not yet initialized!"); + return INSTANCE; } - #endif + + public abstract List getModPlugins(); @ApiStatus.Internal public static class PlugInContainer { From 4eac70c6c3495bd732ef480762145bcd64d8cc6b Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sun, 1 Feb 2026 18:14:41 +0700 Subject: [PATCH 88/92] refactor: WIP split 5 * Fix some errors * Moved AW to :xplat --- fabric/build.gradle.kts | 4 ---- forge/build.gradle.kts | 2 +- .../null2264/cobblegen/forge/CobbleGenForge.java | 1 + xplat/build.gradle.kts | 12 +++++++++++- .../github/null2264/cobblegen/FluidInteraction.java | 2 +- .../null2264/cobblegen/data/config/Config.java | 2 +- .../null2264/cobblegen/integration/CreatePlugin.java | 2 +- .../cobblegen/mixin/core/CobbleGenMixinPlugin.java | 4 ++-- .../java/io/github/null2264/cobblegen/util/Util.java | 8 ++++---- .../src/main/resources/cobblegen.accesswidener | 0 10 files changed, 22 insertions(+), 15 deletions(-) rename {fabric => xplat}/src/main/resources/cobblegen.accesswidener (100%) diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 578e0c57..65f83f36 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -26,10 +26,6 @@ apply(plugin = projectPlugin.id) fun GradlePlugin.configure(configuration: LoomGradleExtensionAPI.() -> Unit = {}) = project.the() .apply { - if (mcVersion.code >= 12105) { - accessWidenerPath = project.file("src/main/resources/cobblegen.accesswidener") - } - runConfigs { named("client") { runDir = "../run/client" diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 1b019031..d3aaf44b 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -144,7 +144,7 @@ dependencies { dep("modCompileOnly", jei(mcVersion, loaderName, common = true, api = true).versioned(CGVer.wildcard())) dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = true).versioned(CGVer.wildcard())) if (project.properties["recipe_viewer"] == "jei") - dep("modCompileOnly", jei(mcVersion, loaderName, common = false, api = false).versioned(CGVer.wildcard())) + dep("modLocalRuntime", jei(mcVersion, loaderName, common = false, api = false).versioned(CGVer.wildcard())) // JEI -> /* FIXME: Broken, somehow diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java index 5bfca4ba..6373b254 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java @@ -16,6 +16,7 @@ public class CobbleGenForge extends CobbleGen { public CobbleGenForge() { LoaderCompat.init(new LoaderCompatForge()); PluginFinder.init(new PluginFinderForge()); + super.init(); #if MC>=11801 && MC<12105 // I was gonna do RegisterGameTestsEvent like a normal person, but there's a check that I need to bypass otherwise Forge won't register my test net.minecraft.gametest.framework.GameTestRegistry.register(io.github.null2264.cobblegen.gametest.BlockGenerationTest.class); diff --git a/xplat/build.gradle.kts b/xplat/build.gradle.kts index 4d4f29a0..75fb6190 100644 --- a/xplat/build.gradle.kts +++ b/xplat/build.gradle.kts @@ -1,3 +1,4 @@ +import dependencies.jei import dependencies.minecraft as MC plugins { @@ -5,8 +6,13 @@ plugins { id("org.spongepowered.gradle.vanilla") } +val mcVersion: CGVer by extra + minecraft { - version(MC.version(project.ext["mcVersion"] as CGVer)) + version(MC.version(mcVersion)) + if (mcVersion.code >= 12105) { + accessWideners(project.file("src/main/resources/cobblegen.accesswidener")) + } } repositories { @@ -26,7 +32,11 @@ configurations { dependencies { compileOnly(project(":stubs")) + compileOnly("org.spongepowered:mixin:0.8.5") + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.5.3")!!) + + compileOnly(jei(mcVersion, "", common = true, api = true).versioned(CGVer.wildcard())) } artifacts { diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java b/xplat/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java index 0cecf1a5..6b052ac5 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/FluidInteraction.java @@ -101,7 +101,7 @@ public void apply() { count.set(0); CGRegistry registry = new CGRegistryImpl(); - for (PluginFinder.PlugInContainer container : PluginFinder.getModPlugins()) { + for (PluginFinder.PlugInContainer container : PluginFinder.getInstance().getModPlugins()) { String id = container.getModId(); CobbleGenPlugin plugin = container.getPlugin(); diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/data/config/Config.java b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/Config.java index 36c8fc13..7a32e2f0 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/data/config/Config.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/data/config/Config.java @@ -15,7 +15,7 @@ public interface Config { .registerDeserializer(String.class, CGIdentifier.class, (str, m) -> CGIdentifier.of(str)) .build(); - Path path = LoaderCompat.getConfigDir(); + Path path = LoaderCompat.getInstance().getConfigDir(); interface Factory { T load(); diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java index 557705bc..317a2043 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/integration/CreatePlugin.java @@ -46,7 +46,7 @@ public void registerInteraction(CGRegistry registry) { @Override public boolean shouldLoad() { - if (!LoaderCompat.isModLoaded("create")) return false; + if (!LoaderCompat.getInstance().isModLoaded("create")) return false; CreateSupport createSupport = CreateCompatUtil.getCreateSupport(); return createSupport != CreateSupport.NONE; diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java index fb77907f..48572344 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java @@ -32,7 +32,7 @@ public String getRefMapperConfig() { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { if (mixinClassName.contains("CreateFluidReactionsMixin")) { - if (!LoaderCompat.isModLoaded("create")) return false; + if (!LoaderCompat.getInstance().isModLoaded("create")) return false; CreateSupport createSupport = CreateCompatUtil.getCreateSupport(); if (createSupport == CreateSupport.NONE) return false; @@ -47,7 +47,7 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { // Datapack will not register automatically in Fabric without FAPI. // I usually prefer not depending on FAPI, but I'll make this one an exception... // because I ain't dealing with Resource Pack loading ever again - if (LoaderCompat.isFabricLike() && !LoaderCompat.isModLoaded("fabric-resource-loader-v0")) { + if (LoaderCompat.getInstance().isFabricLike() && !LoaderCompat.getInstance().isModLoaded("fabric-resource-loader-v0")) { CGLog.warn(() -> "Fabric API is required to load CobbleGen's GameTests!"); return false; } diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/util/Util.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/Util.java index ed7ccbaf..e3367b59 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/util/Util.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/util/Util.java @@ -47,13 +47,13 @@ public static Optional optional(@Nullable T nullable) { } public static boolean isPortingLibLoaded() { - return LoaderCompat.isModLoaded("porting_lib"); + return LoaderCompat.getInstance().isModLoaded("porting_lib"); } public static boolean isAnyRecipeViewerLoaded() { - return LoaderCompat.isModLoaded("roughlyenoughitems") || - LoaderCompat.isModLoaded("jei") || - LoaderCompat.isModLoaded("emi"); + return LoaderCompat.getInstance().isModLoaded("roughlyenoughitems") || + LoaderCompat.getInstance().isModLoaded("jei") || + LoaderCompat.getInstance().isModLoaded("emi"); } public static Fluid getFluid(CGIdentifier id) { diff --git a/fabric/src/main/resources/cobblegen.accesswidener b/xplat/src/main/resources/cobblegen.accesswidener similarity index 100% rename from fabric/src/main/resources/cobblegen.accesswidener rename to xplat/src/main/resources/cobblegen.accesswidener From 181763c826cdac3543ea8a36f1b87bee44104330 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Sun, 1 Feb 2026 19:49:05 +0700 Subject: [PATCH 89/92] refactor: WIP split 6 * Almost there, maybe? --- build.gradle.kts | 2 +- .../fabric/compat/LoaderCompatFabric.java | 10 +++ .../fabric/compat/ModContainerFabric.java | 22 +++++ .../forge/compat/LoaderCompatForge.java | 10 +++ .../forge/compat/ModContainerForge.java | 49 ++++++++++++ xplat/build.gradle.kts | 2 + .../cobblegen/compat/LoaderCompat.java | 11 +++ .../cobblegen/compat/ModContainerCompat.java | 80 +------------------ .../integration/create/CreateCompatUtil.java | 4 +- .../network/FriendlyByteBuf/ByteBufExt.java | 2 +- .../minecraft/world/level/Level/LevelExt.java | 2 +- .../level/LevelAccessor/LevelAccessorExt.java | 2 +- 12 files changed, 113 insertions(+), 83 deletions(-) create mode 100644 fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/ModContainerFabric.java create mode 100644 forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java rename xplat/src/main/java/{io/github/null2264/cobblegen => xplat}/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java (97%) rename xplat/src/main/java/{io/github/null2264/cobblegen => xplat}/extensions/net/minecraft/world/level/Level/LevelExt.java (82%) rename xplat/src/main/java/{io/github/null2264/cobblegen => xplat}/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java (95%) diff --git a/build.gradle.kts b/build.gradle.kts index 30b234a9..84b26791 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -121,7 +121,7 @@ subprojects { configurations.testAnnotationProcessor.get().extendsFrom(this) } - if (project == project(":forge")) { + if (isForge) { afterEvaluate { if (mcVersion.code <= 12108) { configurations.named("additionalRuntimeClasspath").get().extendsFrom(shade) diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java index a9512e2e..0a321749 100644 --- a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java @@ -1,6 +1,7 @@ package io.github.null2264.cobblegen.forge.compat; import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.compat.ModContainerCompat; import java.nio.file.Path; @@ -33,4 +34,13 @@ public Path getConfigDir() { public LoaderType getType() { return LoaderType.FABRIC; } + + @Override + public ModContainerCompat getMod(String modId) { + if (isModCached(modId)) return super.getMod(modId); + + ModContainerCompat rt = new ModContainerFabric(modid); + CACHED.put(modid, rt); + return rt; + } } diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/ModContainerFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/ModContainerFabric.java new file mode 100644 index 00000000..96ff0ae7 --- /dev/null +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/ModContainerFabric.java @@ -0,0 +1,22 @@ +package io.github.null2264.cobblegen.fabric.compat; + +import io.github.null2264.cobblegen.compat.ModContainerCompat; + +public class ModContainerFabric extends ModContainerCompat { + + private final net.fabricmc.loader.api.ModContainer container; + + public ModContainerFabric(String modid) { + this.container = net.fabricmc.loader.api.FabricLoader.getInstance().getModContainer(modid) + #if MC<=11605 + .orElseThrow(NullPointerException::new); + #else + .orElseThrow(); + #endif + } + + @Override + public String getVersionString() { + return container.getMetadata().getVersion().getFriendlyString(); + } +} diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java index 90c7b683..a2358517 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java @@ -1,6 +1,7 @@ package io.github.null2264.cobblegen.forge.compat; import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.compat.ModContainerCompat; import java.nio.file.Path; @@ -37,4 +38,13 @@ public LoaderType getType() { return LoaderType.FORGE; #endif } + + @Override + public ModContainerCompat getMod(String modId) { + if (isModCached(modId)) return super.getMod(modId); + + ModContainerCompat rt = new ModContainerForge(modid); + CACHED.put(modid, rt); + return rt; + } } diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java new file mode 100644 index 00000000..d9025270 --- /dev/null +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java @@ -0,0 +1,49 @@ +package io.github.null2264.cobblegen.forge.compat; + +import io.github.null2264.cobblegen.compat.ModContainerCompat; + +#if MC>=12002 +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.LoadingModList; +import net.neoforged.neoforgespi.language.IModInfo; +#else +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.loading.LoadingModList; +import net.minecraftforge.forgespi.language.IModInfo; +#endif + +public class ModContainerForge extends ModContainerCompat { + + private final IModInfo container; + + public ModContainerForge(String modid) { + IModInfo modInfo; + if (ModList.get() == null) // mainly for MixinConfigPlugin + // I hate this... but should be fine since it happened on loading state + this.container = LoadingModList.get() + .getModFileById(modid) + .getMods() + .stream() + .filter(i -> i.getModId().equals(modid)) + .findFirst() + #if MC<=11605 + .orElseThrow(NullPointerException::new); + #else + .orElseThrow(); + #endif + else + this.container = ModList.get() + .getModContainerById(modid) + #if MC<=11605 + .orElseThrow(NullPointerException::new) + #else + .orElseThrow() + #endif + .getModInfo(); + } + + @Override + public String getVersionString() { + return container.getVersion().toString(); + } +} diff --git a/xplat/build.gradle.kts b/xplat/build.gradle.kts index 75fb6190..12573324 100644 --- a/xplat/build.gradle.kts +++ b/xplat/build.gradle.kts @@ -35,6 +35,8 @@ dependencies { compileOnly("org.spongepowered:mixin:0.8.5") compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.5.3")!!) + compileOnly("org.ow2.asm:asm:9.9") + compileOnly("org.ow2.asm:asm-tree:9.9") compileOnly(jei(mcVersion, "", common = true, api = true).versioned(CGVer.wildcard())) } diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java index 227269dd..b4232290 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java @@ -1,6 +1,8 @@ package io.github.null2264.cobblegen.compat; import java.nio.file.Path; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; #if FABRIC import net.fabricmc.loader.api.FabricLoader; @@ -14,6 +16,7 @@ public abstract class LoaderCompat { private static LoaderCompat INSTANCE; + private static ConcurrentMap CACHED_CONTAINER = new ConcurrentHashMap<>(); public static void init(LoaderCompat impl) { if (INSTANCE != null) throw new IllegalStateException("Already initialized!"); @@ -31,6 +34,14 @@ public static LoaderCompat getInstance() { public abstract LoaderType getType(); + public boolean isModCached(String modId) { + return CACHED_CONTAINER.containsKey(modId); + } + + public ModContainerCompat getMod(String modId) { + return CACHED_CONTAINER.get(modId); + } + public Boolean isFabric() { return getType() == LoaderType.FABRIC; } diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java index eb492cb0..cf2e806c 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/compat/ModContainerCompat.java @@ -1,82 +1,8 @@ package io.github.null2264.cobblegen.compat; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +public abstract class ModContainerCompat { -#if FORGE - #if FORGE==1 -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.loading.LoadingModList; -import net.minecraftforge.forgespi.language.IModInfo; - #else -import net.neoforged.fml.ModList; -import net.neoforged.fml.loading.LoadingModList; -import net.neoforged.neoforgespi.language.IModInfo; - #endif -#endif + protected ModContainerCompat() {} -public class ModContainerCompat { - public static ConcurrentMap CACHED = new ConcurrentHashMap<>(); - private final - #if FABRIC - net.fabricmc.loader.api.ModContainer - #else - IModInfo - #endif - container; - - private ModContainerCompat(String modid) { - #if FORGE - IModInfo modInfo; - if (ModList.get() == null) // mainly for MixinConfigPlugin - // I hate this... but should be fine since it happened on loading state - modInfo = LoadingModList.get() - .getModFileById(modid) - .getMods() - .stream() - .filter(i -> i.getModId().equals(modid)) - .findFirst() - #if MC<=11605 - .orElseThrow(NullPointerException::new); - #else - .orElseThrow(); - #endif - else - modInfo = ModList.get() - .getModContainerById(modid) - #if MC<=11605 - .orElseThrow(NullPointerException::new) - #else - .orElseThrow() - #endif - .getModInfo(); - #endif - this.container = - #if FABRIC - net.fabricmc.loader.api.FabricLoader.getInstance().getModContainer(modid) - #if MC<=11605 - .orElseThrow(NullPointerException::new); - #else - .orElseThrow(); - #endif - #else - modInfo; - #endif - } - - public static ModContainerCompat fromLoader(String modid) { - if (CACHED.containsKey(modid)) return CACHED.get(modid); - - ModContainerCompat rt = new ModContainerCompat(modid); - CACHED.put(modid, new ModContainerCompat(modid)); - return rt; - } - - public String getVersionString() { - #if FABRIC - return container.getMetadata().getVersion().getFriendlyString(); - #else - return container.getVersion().toString(); - #endif - } + public abstract String getVersionString(); } diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java index 308e0fc8..59fa9366 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/integration/create/CreateCompatUtil.java @@ -1,6 +1,6 @@ package io.github.null2264.cobblegen.integration.create; -import io.github.null2264.cobblegen.compat.ModContainerCompat; +import io.github.null2264.cobblegen.compat.LoaderCompat; import io.github.null2264.cobblegen.data.config.ConfigMetaData; import io.github.null2264.cobblegen.util.CGLog; import org.jetbrains.annotations.ApiStatus; @@ -21,7 +21,7 @@ public static CreateSupport getCreateSupport() { return CreateSupport.NONE; // We don't support create integration for MC1.16.5 #else try { - String version = ModContainerCompat.fromLoader("create").getVersionString(); + String version = LoaderCompat.getInstance().getMod("create").getVersionString(); ArrayList split = new ArrayList<>(); String patch = "a"; // version = 0.5.1-a-build.69 diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java b/xplat/src/main/java/xplat/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java similarity index 97% rename from xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java rename to xplat/src/main/java/xplat/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java index b4e28729..45599729 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java +++ b/xplat/src/main/java/xplat/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java @@ -1,4 +1,4 @@ -package io.github.null2264.cobblegen.extensions.net.minecraft.network.FriendlyByteBuf; +package xplat.extensions.net.minecraft.network.FriendlyByteBuf; #if MC<=11605 import com.google.common.collect.Lists; diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java b/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/Level/LevelExt.java similarity index 82% rename from xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java rename to xplat/src/main/java/xplat/extensions/net/minecraft/world/level/Level/LevelExt.java index fe893c53..8cbbaad7 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java +++ b/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/Level/LevelExt.java @@ -1,4 +1,4 @@ -package io.github.null2264.cobblegen.extensions.net.minecraft.world.level.Level; +package xplat.extensions.net.minecraft.world.level.Level; #if MC>12101 import manifold.ext.rt.api.This; diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java b/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java similarity index 95% rename from xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java rename to xplat/src/main/java/xplat/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java index 01de039a..02367c30 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java +++ b/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java @@ -1,5 +1,5 @@ #if FORGE && MC<12002 -package io.github.null2264.cobblegen.extensions.net.minecraft.world.level.LevelAccessor; +package xplat.extensions.net.minecraft.world.level.LevelAccessor; import net.minecraft.core.RegistryAccess; import net.minecraft.world.level.LevelAccessor; From 53e34c46929ecdf990532a7e472e1178de77f488 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Mon, 2 Feb 2026 08:00:38 +0700 Subject: [PATCH 90/92] refactor: WIP split 7 * Fabric launched properly tho still need to clean up more #if FABRIC and #if FORGE remnants --- build.gradle.kts | 2 +- .../src/main/kotlin/multiloader.gradle.kts | 4 ++-- fabric/build.gradle.kts | 3 +++ .../cobblegen/fabric/CobbleGenFabric.java | 2 -- .../cobblegen/fabric/CobbleGenPreLaunch.java | 13 ++++++------- .../fabric/compat/LoaderCompatFabric.java | 12 ++++++++++-- .../mixin/core/CobbleGenMixinPluginFabric.java | 17 +++++++++++++++++ .../cobblegen/forge/CobbleGenForge.java | 12 ++++-------- .../forge/compat/LoaderCompatForge.java | 4 ++-- .../mixin/core/CobbleGenMixinPluginForge.java | 17 +++++++++++++++++ .../network/FriendlyByteBuf/ByteBufExt.java | 2 +- .../minecraft/world/level/Level/LevelExt.java | 2 +- .../level/LevelAccessor/LevelAccessorExt.java | 0 .../cobblegen/compat/LoaderCompat.java | 11 +---------- .../viewer/jei/FluidInteractionCategory.java | 18 ++++++++++++++++-- .../mixin/core/CobbleGenMixinPlugin.java | 8 +++++--- .../cobblegen/util/mc/MCConstants.java | 7 +++++++ 17 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/core/CobbleGenMixinPluginFabric.java create mode 100644 forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/core/CobbleGenMixinPluginForge.java rename xplat/src/main/java/{xplat => cobblegen}/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java (98%) rename xplat/src/main/java/{xplat => cobblegen}/extensions/net/minecraft/world/level/Level/LevelExt.java (86%) rename xplat/src/main/java/{xplat => cobblegen}/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java (100%) create mode 100644 xplat/src/main/java/io/github/null2264/cobblegen/util/mc/MCConstants.java diff --git a/build.gradle.kts b/build.gradle.kts index 84b26791..f8bffedd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -214,7 +214,7 @@ subprojects { // We can't preprocess resources files with Manifold, so we'll construct the json files manually here instead. - project(":common").file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion) + project.file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion) project.file("build/resources/main/cobblegen.${project.name}.mixins.json").apply { if (isFabric) processMixinsJsonFabric(mcVersion) else processMixinsJsonForge(mcVersion) diff --git a/buildSrc/src/main/kotlin/multiloader.gradle.kts b/buildSrc/src/main/kotlin/multiloader.gradle.kts index 0878fd82..ad3033f8 100644 --- a/buildSrc/src/main/kotlin/multiloader.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader.gradle.kts @@ -2,10 +2,10 @@ plugins { id("java-library") } -val xplatJava by configurations.creating { +val xplatJava: Configuration by configurations.creating { isCanBeResolved = true } -val xplatResources by configurations.creating { +val xplatResources: Configuration by configurations.creating { isCanBeResolved = true } diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 65f83f36..c4505f23 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -26,6 +26,9 @@ apply(plugin = projectPlugin.id) fun GradlePlugin.configure(configuration: LoomGradleExtensionAPI.() -> Unit = {}) = project.the() .apply { + if (mcVersion.code >= 12105) { + accessWidenerPath = project(":xplat").file("src/main/resources/cobblegen.accesswidener") + } runConfigs { named("client") { runDir = "../run/client" diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java index a15c1cee..98546fa3 100644 --- a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenFabric.java @@ -10,8 +10,6 @@ public class CobbleGenFabric extends CobbleGen implements net.fabricmc.api.ModIn @Override public void onInitialize() { - LoaderCompat.init(new LoaderCompatFabric()); - PluginFinder.init(new PluginFinderFabric()); super.init(); } } diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java index f9dc82ba..b400bef4 100644 --- a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/CobbleGenPreLaunch.java @@ -1,14 +1,13 @@ -#if FABRIC package io.github.null2264.cobblegen.fabric; +import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.fabric.util.PluginFinderFabric; +import io.github.null2264.cobblegen.forge.compat.LoaderCompatFabric; +import io.github.null2264.cobblegen.util.PluginFinder; + public class CobbleGenPreLaunch implements net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint { - public CobbleGenPreLaunch() { - #if MC>=12105 - io.github.null2264.cobblegen.gametest.CobbleGenTestLoader.init(); - #endif - } + public CobbleGenPreLaunch() {} @Override public void onPreLaunch() {} } -#endif diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java index 0a321749..9cc082d4 100644 --- a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/compat/LoaderCompatFabric.java @@ -2,9 +2,17 @@ import io.github.null2264.cobblegen.compat.LoaderCompat; import io.github.null2264.cobblegen.compat.ModContainerCompat; +import io.github.null2264.cobblegen.fabric.compat.ModContainerFabric; +import net.fabricmc.loader.api.FabricLoader; import java.nio.file.Path; +#if MC<=11605 +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +#endif + public class LoaderCompatFabric extends LoaderCompat { @Override @@ -39,8 +47,8 @@ public LoaderType getType() { public ModContainerCompat getMod(String modId) { if (isModCached(modId)) return super.getMod(modId); - ModContainerCompat rt = new ModContainerFabric(modid); - CACHED.put(modid, rt); + ModContainerCompat rt = new ModContainerFabric(modId); + CACHED_CONTAINER.put(modId, rt); return rt; } } diff --git a/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/core/CobbleGenMixinPluginFabric.java b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/core/CobbleGenMixinPluginFabric.java new file mode 100644 index 00000000..b38887c9 --- /dev/null +++ b/fabric/src/main/java/io/github/null2264/cobblegen/fabric/mixin/core/CobbleGenMixinPluginFabric.java @@ -0,0 +1,17 @@ +package io.github.null2264.cobblegen.fabric.mixin.core; + +import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.fabric.util.PluginFinderFabric; +import io.github.null2264.cobblegen.forge.compat.LoaderCompatFabric; +import io.github.null2264.cobblegen.mixin.core.CobbleGenMixinPlugin; +import io.github.null2264.cobblegen.util.PluginFinder; + +public class CobbleGenMixinPluginFabric extends CobbleGenMixinPlugin { + + @Override + public void onLoad(String mixinPackage) { + LoaderCompat.init(new LoaderCompatFabric()); + PluginFinder.init(new PluginFinderFabric()); + super.onLoad(mixinPackage); + } +} diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java index 6373b254..aa7bf6f4 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/CobbleGenForge.java @@ -1,21 +1,17 @@ package io.github.null2264.cobblegen.fabric; import io.github.null2264.cobblegen.CobbleGen; -import io.github.null2264.cobblegen.compat.LoaderCompat; -import io.github.null2264.cobblegen.forge.compat.LoaderCompatForge; -import io.github.null2264.cobblegen.forge.util.PluginFinderForge; -import io.github.null2264.cobblegen.util.PluginFinder; + +import static io.github.null2264.cobblegen.CobbleGen.MOD_ID; #if MC>=12002 -@net.neoforged.fml.common.Mod(CobbleGen.MOD_ID) +@net.neoforged.fml.common.Mod(MOD_ID) #else -@net.minecraftforge.fml.common.Mod(CobbleGen.MOD_ID) +@net.minecraftforge.fml.common.Mod(MOD_ID) #endif public class CobbleGenForge extends CobbleGen { public CobbleGenForge() { - LoaderCompat.init(new LoaderCompatForge()); - PluginFinder.init(new PluginFinderForge()); super.init(); #if MC>=11801 && MC<12105 // I was gonna do RegisterGameTestsEvent like a normal person, but there's a check that I need to bypass otherwise Forge won't register my test diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java index a2358517..1cf39594 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/LoaderCompatForge.java @@ -43,8 +43,8 @@ public LoaderType getType() { public ModContainerCompat getMod(String modId) { if (isModCached(modId)) return super.getMod(modId); - ModContainerCompat rt = new ModContainerForge(modid); - CACHED.put(modid, rt); + ModContainerCompat rt = new ModContainerForge(modId); + CACHED_CONTAINER.put(modId, rt); return rt; } } diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/core/CobbleGenMixinPluginForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/core/CobbleGenMixinPluginForge.java new file mode 100644 index 00000000..7f0a4f0e --- /dev/null +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/mixin/core/CobbleGenMixinPluginForge.java @@ -0,0 +1,17 @@ +package io.github.null2264.cobblegen.forge.mixin.core; + +import io.github.null2264.cobblegen.compat.LoaderCompat; +import io.github.null2264.cobblegen.forge.compat.LoaderCompatForge; +import io.github.null2264.cobblegen.forge.util.PluginFinderForge; +import io.github.null2264.cobblegen.mixin.core.CobbleGenMixinPlugin; +import io.github.null2264.cobblegen.util.PluginFinder; + +public class CobbleGenMixinPluginForge extends CobbleGenMixinPlugin { + + @Override + public void onLoad(String mixinPackage) { + LoaderCompat.init(new LoaderCompatForge()); + PluginFinder.init(new PluginFinderForge()); + super.onLoad(mixinPackage); + } +} diff --git a/xplat/src/main/java/xplat/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java b/xplat/src/main/java/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java similarity index 98% rename from xplat/src/main/java/xplat/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java rename to xplat/src/main/java/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java index 45599729..86291934 100644 --- a/xplat/src/main/java/xplat/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java +++ b/xplat/src/main/java/cobblegen/extensions/net/minecraft/network/FriendlyByteBuf/ByteBufExt.java @@ -1,4 +1,4 @@ -package xplat.extensions.net.minecraft.network.FriendlyByteBuf; +package cobblegen.extensions.net.minecraft.network.FriendlyByteBuf; #if MC<=11605 import com.google.common.collect.Lists; diff --git a/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/Level/LevelExt.java b/xplat/src/main/java/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java similarity index 86% rename from xplat/src/main/java/xplat/extensions/net/minecraft/world/level/Level/LevelExt.java rename to xplat/src/main/java/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java index 8cbbaad7..7f3cf1ee 100644 --- a/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/Level/LevelExt.java +++ b/xplat/src/main/java/cobblegen/extensions/net/minecraft/world/level/Level/LevelExt.java @@ -1,4 +1,4 @@ -package xplat.extensions.net.minecraft.world.level.Level; +package cobblegen.extensions.net.minecraft.world.level.Level; #if MC>12101 import manifold.ext.rt.api.This; diff --git a/xplat/src/main/java/xplat/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java b/xplat/src/main/java/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java similarity index 100% rename from xplat/src/main/java/xplat/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java rename to xplat/src/main/java/cobblegen/extensions/net/minecraft/world/level/LevelAccessor/LevelAccessorExt.java diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java index b4232290..7423d8d5 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/compat/LoaderCompat.java @@ -4,19 +4,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -#if FABRIC -import net.fabricmc.loader.api.FabricLoader; - #if MC<=11605 -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Files; - #endif -#endif - public abstract class LoaderCompat { private static LoaderCompat INSTANCE; - private static ConcurrentMap CACHED_CONTAINER = new ConcurrentHashMap<>(); + public static ConcurrentMap CACHED_CONTAINER = new ConcurrentHashMap<>(); public static void init(LoaderCompat impl) { if (INSTANCE != null) throw new IllegalStateException("Already initialized!"); diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java index be31526e..eb696678 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/integration/viewer/jei/FluidInteractionCategory.java @@ -209,9 +209,23 @@ public void draw( Minecraft minecraft = Minecraft.getInstance(); Font font = minecraft.font; var minY = recipe.getResult().minY; - if (minY == null) minY = minecraft.level != null ? minecraft.level.getMinBuildHeight() : 0; + if (minY == null) minY = + minecraft.level != null ? + #if MC>12101 + minecraft.level.getMinY() : + #else + minecraft.level.getMinBuildHeight() : + #endif + 0; var maxY = recipe.getResult().maxY; - if (maxY == null) maxY = minecraft.level != null ? minecraft.level.getMaxBuildHeight() : 256; + if (maxY == null) maxY = + minecraft.level != null ? + #if MC>12101 + minecraft.level.getMaxY() : + #else + minecraft.level.getMaxBuildHeight() : + #endif + 256; List texts = List.of( TextCompat.translatable("cobblegen.info.weight") .append(Component.nullToEmpty(recipe.getResult().weight.toString())), diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java index 48572344..99d2df38 100644 --- a/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java +++ b/xplat/src/main/java/io/github/null2264/cobblegen/mixin/core/CobbleGenMixinPlugin.java @@ -14,12 +14,14 @@ import java.util.Set; import java.util.regex.PatternSyntaxException; -public class CobbleGenMixinPlugin implements IMixinConfigPlugin { +public abstract class CobbleGenMixinPlugin implements IMixinConfigPlugin { + /** + * This function is called even earlier than Fabric's PreLaunch.onPreLaunch + */ @Override public void onLoad(String mixinPackage) { - #if FORGE && MC>=12105 - // This is the earliest entrypoint for Forge that I know of... + #if MC>=12105 io.github.null2264.cobblegen.gametest.CobbleGenTestLoader.init(); #endif } diff --git a/xplat/src/main/java/io/github/null2264/cobblegen/util/mc/MCConstants.java b/xplat/src/main/java/io/github/null2264/cobblegen/util/mc/MCConstants.java new file mode 100644 index 00000000..ca87dee9 --- /dev/null +++ b/xplat/src/main/java/io/github/null2264/cobblegen/util/mc/MCConstants.java @@ -0,0 +1,7 @@ +package io.github.null2264.cobblegen.util.mc; + +/** + * MC-related constants. Do NOT use during mod loading state (e.g. in MixinPlugin) + */ +public class MCConstants { +} From ee07ea2b854049de6ca81b7859ac4884fe48867d Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Mon, 2 Feb 2026 11:43:17 +0700 Subject: [PATCH 91/92] ci: Don't retry on err code 1 and kill daemon before retrying --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6e18db6..78b224a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -121,6 +121,8 @@ jobs: ./gradlew build -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}" && exit 0 c="$?" echo "Try $tries failed. (code:$c)" + [ "$c" = "1" ] && break + ./gradlew --stop # this should free up the memory so we didn't encounter OutOfMemory err sleep 5s tries=$((tries+1)) done From 6f0e51b76560c883fa1d296b0d8e3c72bae60eee Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 4 Feb 2026 15:02:55 +0700 Subject: [PATCH 92/92] fix: Forge now run... kinda --- build.gradle.kts | 19 +++++++++++---- .../src/main/kotlin/ProcessModMetadata.kt | 10 +++++++- .../forge/compat/ModContainerForge.java | 24 +++++++++++++------ .../forge/util/PluginFinderForge.java | 3 ++- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f8bffedd..df4bb645 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,9 +32,15 @@ allprojects { extra["mcVersion"] = mcVersion extra["mcVersionStr"] = mcVersionStr - extra["loaderName"] = loaderName val isFabric = project == project(":fabric") - val isNeo = !isFabric && mcVersion.code >= 12002 + val isForge = project == project(":forge") + val isNeo = isForge && mcVersion.code >= 12002 + extra["loaderName"] = when { + isFabric -> "fabric" + isNeo -> "neoforge" + isForge -> "forge" + else -> "" + } base.archivesName.set(rootProject.properties["archives_base_name"] as? String ?: "") @@ -104,6 +110,12 @@ subprojects { val isFabric = project == project(":fabric") val isForge = project == project(":forge") val isNeo = isForge && mcVersion.code >= 12002 + val loaderName = when { + isFabric -> "fabric" + isNeo -> "neoforge" + isForge -> "forge" + else -> "" + } apply(plugin = "java") apply(plugin = "com.gradleup.shadow") @@ -212,9 +224,8 @@ subprojects { .writeStructureAsNbt(generateStructure(true)) } - // We can't preprocess resources files with Manifold, so we'll construct the json files manually here instead. - project.file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion) + project.file("build/resources/main/cobblegen.mixins.json").processMixinsJson(mcVersion, if (isFabric) "fabric" else "forge") project.file("build/resources/main/cobblegen.${project.name}.mixins.json").apply { if (isFabric) processMixinsJsonFabric(mcVersion) else processMixinsJsonForge(mcVersion) diff --git a/buildSrc/src/main/kotlin/ProcessModMetadata.kt b/buildSrc/src/main/kotlin/ProcessModMetadata.kt index 0f38c437..01bcbff6 100644 --- a/buildSrc/src/main/kotlin/ProcessModMetadata.kt +++ b/buildSrc/src/main/kotlin/ProcessModMetadata.kt @@ -2,6 +2,7 @@ import java.io.File import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive +import java.util.Locale fun File.processModsToml( mcVersion: CGVer, @@ -60,7 +61,7 @@ fun File.processMixinsJsonForge(mcVersion: CGVer) { ) } -fun File.processMixinsJson(mcVersion: CGVer) { +fun File.processMixinsJson(mcVersion: CGVer, loaderName: String) { val both = buildList { if (mcVersion.code >= 12005) addJson("network.packet.CustomPacketPayloadMixin") addJson("CommandsMixin") @@ -94,6 +95,13 @@ fun File.processMixinsJson(mcVersion: CGVer) { set("mixins", JsonArray(both)) set("client", JsonArray(client)) set("server", JsonArray(server)) + set("plugin", JsonPrimitive("io.github.null2264.cobblegen${if (!loaderName.isEmpty()) ".$loaderName" else ""}.mixin.core.CobbleGenMixinPlugin${ + loaderName.replaceFirstChar { + if (it.isLowerCase()) it.titlecase( + Locale.getDefault() + ) else it.toString() + } + }")) } ) writeText(prettyJson.encodeToString(JsonObject.serializer(), mixinsJson)) diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java index d9025270..875ff223 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/compat/ModContainerForge.java @@ -4,6 +4,9 @@ #if MC>=12002 import net.neoforged.fml.ModList; +#if MC>=12111 +import net.neoforged.fml.loading.FMLLoader; +#endif import net.neoforged.fml.loading.LoadingModList; import net.neoforged.neoforgespi.language.IModInfo; #else @@ -16,30 +19,37 @@ public class ModContainerForge extends ModContainerCompat { private final IModInfo container; - public ModContainerForge(String modid) { + public ModContainerForge(String modId) { IModInfo modInfo; - if (ModList.get() == null) // mainly for MixinConfigPlugin + if (ModList.get() == null) { // mainly for MixinConfigPlugin + LoadingModList modList = + #if MC>=12111 + FMLLoader.getCurrent().getLoadingModList(); + #else + LoadingModList.get(); + #endif // I hate this... but should be fine since it happened on loading state - this.container = LoadingModList.get() - .getModFileById(modid) + this.container = modList + .getModFileById(modId) .getMods() .stream() - .filter(i -> i.getModId().equals(modid)) + .filter(i -> i.getModId().equals(modId)) .findFirst() #if MC<=11605 .orElseThrow(NullPointerException::new); #else .orElseThrow(); #endif - else + } else { this.container = ModList.get() - .getModContainerById(modid) + .getModContainerById(modId) #if MC<=11605 .orElseThrow(NullPointerException::new) #else .orElseThrow() #endif .getModInfo(); + } } @Override diff --git a/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java b/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java index b48bc35b..b982b4dd 100644 --- a/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java +++ b/forge/src/main/java/io/github/null2264/cobblegen/forge/util/PluginFinderForge.java @@ -2,12 +2,14 @@ import io.github.null2264.cobblegen.CGPlugin; import io.github.null2264.cobblegen.CobbleGenPlugin; +import io.github.null2264.cobblegen.util.CGLog; import io.github.null2264.cobblegen.util.PluginFinder; import java.lang.reflect.Constructor; import org.objectweb.asm.Type; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static io.github.null2264.cobblegen.compat.CollectionCompat.streamToList; @@ -43,7 +45,6 @@ public static List getInstances(Class annotationClass, C Iterable annotations = data.getAnnotations(); for (ModFileScanData.AnnotationData a : annotations) { - if (!(Objects.equals( #if MC>11605 a.annotationType(),