From 124c51c48f616d2d016bd6d103e6c242b39400df Mon Sep 17 00:00:00 2001 From: NotCoded Date: Sun, 19 Jul 2026 01:07:08 +0200 Subject: [PATCH 1/2] build: snapshot in-progress 26.x stonecutter migration Working-tree state of the Stonecutter 0.9.6 rework adding 26.x targets: per-loader buildscripts, TOML version properties, loom-no-remap for unobfuscated 26.x, reusable CI workflows. --- .github/workflows/build.yml | 54 +---- .github/workflows/build_reusable.yml | 58 +++++ .github/workflows/release.yml | 49 ++++ .gitignore | 10 +- .sc_active_version | 1 + CHANGES.md | 2 +- build.fabric.gradle.kts | 135 +++++++++++ build.forge.gradle.kts | 124 ++++++++++ build.gradle.kts | 217 ------------------ build.neoforge.gradle.kts | 137 +++++++++++ buildSrc/build.gradle.kts | 13 +- buildSrc/src/main/kotlin/LoomPluginChooser.kt | 28 +++ buildSrc/src/main/kotlin/build-extensions.kt | 31 --- .../src/main/kotlin/neoforge-mutex.gradle.kts | 13 ++ gradle.properties | 34 +-- gradle/libs.versions.toml | 12 + gradle/wrapper/gradle-wrapper.jar | Bin 43764 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 11 +- gradlew.bat | 36 +-- settings.gradle.kts | 39 ++-- .../java/net/notcoded/xyzcopy/XYZCopy.java | 16 +- .../xyzcopy/mixin/KeyMappingAccessor.java | 12 + .../xyzcopy/mixin/KeyboardHandlerMixin.java | 32 +-- .../xyzcopy/mixin/MinecraftMixin.java | 4 + .../platforms/fabric/XYZCopyFabric.java | 17 +- .../xyzcopy/platforms/forge/XYZCopyForge.java | 48 +++- .../notcoded/xyzcopy/util/LocationUtil.java | 61 +++-- .../notcoded/xyzcopy/util/VersionUtil.java | 47 ++-- src/main/resources/fabric.mod.json | 4 +- src/main/resources/xyzcopy.accesswidener | 2 - src/main/resources/xyzcopy.mixins.json | 5 +- stonecutter.gradle.kts | 56 ++--- stonecutter.properties.toml | 197 ++++++++++++++++ versions/1.16.5-fabric/gradle.properties | 10 - versions/1.16.5-forge/gradle.properties | 11 - versions/1.17.1-fabric/gradle.properties | 10 - versions/1.17.1-forge/gradle.properties | 12 - versions/1.18.2-forge/gradle.properties | 11 - versions/1.19-fabric/gradle.properties | 10 - versions/1.19-forge/gradle.properties | 11 - versions/1.19.4-fabric/gradle.properties | 10 - versions/1.19.4-forge/gradle.properties | 11 - versions/1.20.1-fabric/gradle.properties | 10 - versions/1.20.1-forge/gradle.properties | 11 - versions/1.20.4-neoforge/gradle.properties | 11 - versions/1.20.6-forge/gradle.properties | 11 - versions/1.20.6-neoforge/gradle.properties | 11 - versions/1.21.11-fabric/gradle.properties | 11 - versions/1.21.11-forge/gradle.properties | 11 - versions/1.21.11-neoforge/gradle.properties | 11 - versions/1.21.6-forge/gradle.properties | 11 - versions/1.21.9-fabric/gradle.properties | 10 - versions/1.21.9-forge/gradle.properties | 11 - versions/1.21.9-neoforge/gradle.properties | 11 - versions/26.1-fabric/gradle.properties | 10 - 56 files changed, 999 insertions(+), 746 deletions(-) create mode 100644 .github/workflows/build_reusable.yml create mode 100644 .github/workflows/release.yml create mode 100644 .sc_active_version create mode 100644 build.fabric.gradle.kts create mode 100644 build.forge.gradle.kts delete mode 100644 build.gradle.kts create mode 100644 build.neoforge.gradle.kts create mode 100644 buildSrc/src/main/kotlin/LoomPluginChooser.kt delete mode 100644 buildSrc/src/main/kotlin/build-extensions.kt create mode 100644 buildSrc/src/main/kotlin/neoforge-mutex.gradle.kts create mode 100644 gradle/libs.versions.toml create mode 100644 src/main/java/net/notcoded/xyzcopy/mixin/KeyMappingAccessor.java delete mode 100644 src/main/resources/xyzcopy.accesswidener create mode 100644 stonecutter.properties.toml delete mode 100644 versions/1.16.5-fabric/gradle.properties delete mode 100644 versions/1.16.5-forge/gradle.properties delete mode 100644 versions/1.17.1-fabric/gradle.properties delete mode 100644 versions/1.17.1-forge/gradle.properties delete mode 100644 versions/1.18.2-forge/gradle.properties delete mode 100644 versions/1.19-fabric/gradle.properties delete mode 100644 versions/1.19-forge/gradle.properties delete mode 100644 versions/1.19.4-fabric/gradle.properties delete mode 100644 versions/1.19.4-forge/gradle.properties delete mode 100644 versions/1.20.1-fabric/gradle.properties delete mode 100644 versions/1.20.1-forge/gradle.properties delete mode 100644 versions/1.20.4-neoforge/gradle.properties delete mode 100644 versions/1.20.6-forge/gradle.properties delete mode 100644 versions/1.20.6-neoforge/gradle.properties delete mode 100644 versions/1.21.11-fabric/gradle.properties delete mode 100644 versions/1.21.11-forge/gradle.properties delete mode 100644 versions/1.21.11-neoforge/gradle.properties delete mode 100644 versions/1.21.6-forge/gradle.properties delete mode 100644 versions/1.21.9-fabric/gradle.properties delete mode 100644 versions/1.21.9-forge/gradle.properties delete mode 100644 versions/1.21.9-neoforge/gradle.properties delete mode 100644 versions/26.1-fabric/gradle.properties diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c451830..a06e02b 100755 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,55 +1,9 @@ -# Automatically build the project and run any configured tests for every push -# and submitted pull request. This can help catch issues that only occur on -# certain platforms or Java versions, and provides a first line of defence -# against bad commits. - name: build on: [pull_request, push] +permissions: + contents: read + jobs: build: - strategy: - matrix: - java: [ - 25, - ] - - distribution: [ - "temurin", - ] - - os: [ubuntu-24.04] - - runs-on: ${{ matrix.os }} - steps: - - name: checkout repository - uses: actions/checkout@v6 - - name: validate gradle wrapper - uses: gradle/actions/wrapper-validation@v5 - - name: setup jdk ${{ matrix.java }} - uses: actions/setup-java@v5 - with: - java-version: ${{ matrix.java }} - distribution: ${{ matrix.distribution }} - cache: 'gradle' - - name: make gradle wrapper executable - run: chmod +x ./gradlew - - name: cache gradle - uses: actions/cache@v5 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - ~/.gradle/build-cache - ~/.gradle/daemon - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - ${{ runner.os }}- - - name: build - run: ./gradlew chiseledBuild --build-cache --no-configuration-cache - - name: capture build artifacts - uses: actions/upload-artifact@v6 - with: - name: Artifacts - path: build/libs/ + uses: ./.github/workflows/build_reusable.yml diff --git a/.github/workflows/build_reusable.yml b/.github/workflows/build_reusable.yml new file mode 100644 index 0000000..b5db5ee --- /dev/null +++ b/.github/workflows/build_reusable.yml @@ -0,0 +1,58 @@ +name: build (reusable) + +on: + workflow_call: + inputs: + publish: + description: Also upload every target to Modrinth and CurseForge. + type: boolean + default: false + secrets: + MODRINTH_API_KEY: + required: false + CURSEFORGE_TOKEN: + required: false + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - name: checkout repository + uses: actions/checkout@v6 + + - name: validate gradle wrapper + uses: gradle/actions/wrapper-validation@v5 + # One JDK for everything: the buildscripts pin a Java 25 toolchain and set + # options.release per target, so javac emits the right bytecode level (8 for + # 1.16.5, 17 for 1.18-1.20.4, ...) without a JDK per Minecraft version. + - name: setup jdk + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: 25 + + - name: setup gradle + uses: gradle/actions/setup-gradle@v4 + + - name: make gradle wrapper executable + run: chmod +x ./gradlew + + - name: build all targets + run: ./gradlew chiseledBuild --continue --stacktrace --build-cache --no-configuration-cache + + # -PpublishRelease is what flips publishMods out of dry-run mode. Without this step + # (or without that flag) nothing is ever uploaded. + - name: publish all targets + if: inputs.publish + env: + MODRINTH_API_KEY: ${{ secrets.MODRINTH_API_KEY }} + CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }} + run: ./gradlew chiseledPublish -PpublishRelease --stacktrace --build-cache --no-configuration-cache + + - name: capture build artifacts + if: always() + uses: actions/upload-artifact@v6 + with: + name: xyzcopy-jars + path: build/libs/**/*.jar + if-no-files-found: warn diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..91c38e8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +# Tag-triggered release: verifies the tag matches mod.version, builds every target and +# uploads them to Modrinth/CurseForge. The jars are also kept as workflow artifacts. +# +# Requires two repository secrets: MODRINTH_API_KEY and CURSEFORGE_TOKEN. +# Tag either `1.0.0` or `v1.0.0` — both are accepted as long as the number matches +# mod.version in stonecutter.properties.toml. + +name: release + +on: + push: + tags: + - '*' + +permissions: + contents: read + +jobs: + validate: + name: validate tag + runs-on: ubuntu-24.04 + steps: + - name: checkout repository + uses: actions/checkout@v6 + + # Guards against tagging a commit whose mod.version was never bumped, which would + # otherwise publish a release under the previous version number. + - name: check tag matches mod.version + run: | + set -euo pipefail + tag="${GITHUB_REF_NAME#v}" + version="$(sed -n 's/^mod\.version[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' stonecutter.properties.toml)" + if [ -z "$version" ]; then + echo "::error::could not read mod.version from stonecutter.properties.toml" + exit 1 + fi + if [ "$tag" != "$version" ]; then + echo "::error::tag '${GITHUB_REF_NAME}' does not match mod.version '${version}'" + exit 1 + fi + echo "tag '${GITHUB_REF_NAME}' matches mod.version '${version}'" + + publish: + name: build and publish + needs: validate + uses: ./.github/workflows/build_reusable.yml + with: + publish: true + secrets: inherit diff --git a/.gitignore b/.gitignore index 3dbbae6..7ac7076 100755 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,11 @@ .VolumeIcon.icns .com.apple.timemachine.donotpresent +# shhhh ai +.ai +.claude +.codex + # Directories potentially created on remote AFP share .AppleDB .AppleDesktop @@ -95,4 +100,7 @@ run/ # architectury .architectury-transformer\debug.log -.architectury-transformer/debug.log \ No newline at end of file +.architectury-transformer/debug.log + +# superpowers +docs/superpowers/ \ No newline at end of file diff --git a/.sc_active_version b/.sc_active_version new file mode 100644 index 0000000..0bd139e --- /dev/null +++ b/.sc_active_version @@ -0,0 +1 @@ +26.1-fabric \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index ff4ad0b..c12ef66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,2 +1,2 @@ changes: -- initial release \ No newline at end of file +- 26.x support \ No newline at end of file diff --git a/build.fabric.gradle.kts b/build.fabric.gradle.kts new file mode 100644 index 0000000..c9e2446 --- /dev/null +++ b/build.fabric.gradle.kts @@ -0,0 +1,135 @@ +import dev.kikugie.stonecutter.data.deserialization.SCList +import dev.kikugie.stonecutter.data.deserialization.SCPrimitive +import me.modmuss50.mpp.ReleaseType + +plugins { + id("loom-plugin-chooser") + alias(libs.plugins.mod.publish) +} + +val modVersion = property("mod.version") as String +val modId = property("mod.id") as String +val mcCompat = property("mod.mc_compat") as String +val versionName = property("mod.version_name") as String +val obfuscated = sc.current.version.startsWith("1.") +val keyBindingApi = if (sc.current.parsed >= "26.1") "fabric-key-mapping-api-v1" else "fabric-key-binding-api-v1" + +version = "$modVersion+$versionName-fabric" +group = property("mod.group") as String +base.archivesName = modId + +val requiredJava: JavaVersion = when { + sc.current.parsed >= "26.1" -> JavaVersion.VERSION_25 + sc.current.parsed >= "1.20.5" -> JavaVersion.VERSION_21 + sc.current.parsed >= "1.18" -> JavaVersion.VERSION_17 + sc.current.parsed >= "1.17" -> JavaVersion.VERSION_16 + else -> JavaVersion.VERSION_1_8 +} + +repositories { + maven("https://maven.shedaniel.me/") + maven("https://maven.terraformersmc.com/releases/") +} + +dependencies { + minecraft("com.mojang:minecraft:${sc.current.version}") + if (obfuscated) mappings(loom.officialMojangMappings()) + + modImplementation("net.fabricmc:fabric-loader:${property("deps.fabric_loader")}") + modImplementation("me.shedaniel.cloth:cloth-config-fabric:${property("deps.cloth_config")}") + modImplementation("com.terraformersmc:modmenu:${property("deps.mod_menu")}") + modImplementation("net.fabricmc.fabric-api:fabric-api:${property("deps.fabric_api")}") +} + +loom { + runConfigs.all { + generateRunConfig = true + runDirectory = rootProject.layout.projectDirectory.dir("run") + } + decompilers { + get("vineflower").apply { options.put("mark-corresponding-synthetics", "1") } + } +} + +java { + withSourcesJar() + toolchain { + vendor = JvmVendorSpec.ADOPTIUM + languageVersion = JavaLanguageVersion.of(25) + } +} + +tasks.withType().configureEach { + options.release = requiredJava.majorVersion.toInt() +} + +val runLauncher = extensions.getByType().launcherFor { + languageVersion = JavaLanguageVersion.of(requiredJava.majorVersion) + vendor = JvmVendorSpec.ADOPTIUM +} +tasks.withType().matching { it.name.startsWith("run") }.configureEach { + javaLauncher = runLauncher +} + +val mainJar = tasks.named(if (obfuscated) "remapJar" else "jar") +val srcJar = tasks.named(if (obfuscated) "remapSourcesJar" else "sourcesJar") + +tasks { + processResources { + val mixinJava = "JAVA_${requiredJava.majorVersion}" + val props = mapOf("version" to modVersion, "minecraftVersion" to mcCompat, "javaVersion" to requiredJava.majorVersion, "keyBindingApi" to keyBindingApi) + props.forEach { (k, v) -> inputs.property(k, v) } + filesMatching("fabric.mod.json") { expand(props) } + filesMatching("*.mixins.json") { expand("java" to mixinJava) } + exclude("META-INF/mods.toml", "META-INF/neoforge.mods.toml", "pack.mcmeta") + } + register("buildAndCollect") { + group = "build" + from(mainJar, srcJar) + into(rootProject.layout.buildDirectory.file("libs/$modVersion/fabric")) + } +} + +val modrinthToken = providers.environmentVariable("MODRINTH_API_KEY") + .orElse(providers.systemProperty("MODRINTH_API_KEY")) +val curseforgeToken = providers.environmentVariable("CURSEFORGE_TOKEN") + .orElse(providers.systemProperty("CURSEFORGE_TOKEN")) + +val mcReleases = (sc.properties.raw("mod", "mc_releases") as SCList) + .map { (it as SCPrimitive).content.toString() } + +publishMods { + file = tasks.named(if (obfuscated) "remapJar" else "jar") + .flatMap { it.archiveFile } + type = ReleaseType.STABLE + displayName = "Fabric | $versionName [v$modVersion]" + version = project.version.toString() + changelog = "## [Fabric API](https://modrinth.com/mod/fabric-api) is required for Custom Keybinds!\n\n" + + rootProject.file("CHANGES.md").readText() + modLoaders.add("fabric") + modLoaders.add("quilt") + + dryRun = !project.hasProperty("publishRelease") + + modrinth { + accessToken = modrinthToken + projectId = "w4Xqquyv" + minecraftVersions.addAll(mcReleases) + requires("cloth-config") + optional("fabric-api") + optional("modmenu") + } + + curseforge { + accessToken = curseforgeToken + projectId = "1421731" + minecraftVersions.addAll(mcReleases) + javaVersions.add(requiredJava) + client = true + server = false + changelogType = "markdown" + requires("cloth-config") + optional("fabric-api") + optional("modmenu") + } +} diff --git a/build.forge.gradle.kts b/build.forge.gradle.kts new file mode 100644 index 0000000..860dff2 --- /dev/null +++ b/build.forge.gradle.kts @@ -0,0 +1,124 @@ +import com.sun.imageio.plugins.jpeg.JPEG.vendor +import dev.kikugie.stonecutter.data.deserialization.SCList +import dev.kikugie.stonecutter.data.deserialization.SCPrimitive +import jdk.jfr.internal.JVM.exclude +import me.modmuss50.mpp.ReleaseType +import org.gradle.internal.impldep.org.jsoup.nodes.Entities + +plugins { + id("loom-plugin-chooser") + alias(libs.plugins.mod.publish) +} + +val modVersion = property("mod.version") as String +val modId = property("mod.id") as String +val mcCompat = property("mod.mc_compat") as String +val versionName = property("mod.version_name") as String +val clothSep = if (sc.current.version == "1.16.5") "-" else "_" + +version = "$modVersion+$versionName-forge" +group = property("mod.group") as String +Entities.EscapeMode.base.archivesName = modId + +val requiredJava: JavaVersion = when { + sc.current.parsed >= "26.1" -> JavaVersion.VERSION_25 + sc.current.parsed >= "1.20.5" -> JavaVersion.VERSION_21 + sc.current.parsed >= "1.18" -> JavaVersion.VERSION_17 + sc.current.parsed >= "1.17" -> JavaVersion.VERSION_16 + else -> JavaVersion.VERSION_1_8 +} + +repositories { + maven("https://maven.shedaniel.me/") + maven("https://maven.minecraftforge.net/") +} + +dependencies { + minecraft("com.mojang:minecraft:${sc.current.version}") + mappings(loom.officialMojangMappings()) + "forge"("net.minecraftforge:forge:${sc.current.version}-${property("deps.forge_loader")}") + modImplementation("me.shedaniel.cloth:cloth-config-forge:${property("deps.cloth_config")}") +} + +loom { + forge { + mixinConfig("xyzcopy.mixins.json") + } + decompilers { + get("vineflower").apply { options.put("mark-corresponding-synthetics", "1") } + } +} + +java { + withSourcesJar() + toolchain { + vendor = JvmVendorSpec.ADOPTIUM + languageVersion = JavaLanguageVersion.of(25) + } +} + +tasks.withType().configureEach { + options.release = requiredJava.majorVersion.toInt() +} + +val runLauncher = extensions.getByType().launcherFor { + languageVersion = JavaLanguageVersion.of(requiredJava.majorVersion) + vendor = JvmVendorSpec.ADOPTIUM +} +tasks.withType().matching { it.name.startsWith("run") }.configureEach { + javaLauncher = runLauncher +} + + +tasks { + processResources { + val mixinJava = "JAVA_${requiredJava.majorVersion}" + val props = mapOf("version" to modVersion, "minecraftVersion" to mcCompat, "javaVersion" to requiredJava.majorVersion, "cloth_config_separator" to clothSep) + props.forEach { (k, v) -> inputs.property(k, v) } + filesMatching("META-INF/mods.toml") { expand(props) } + filesMatching("*.mixins.json") { expand("java" to mixinJava) } + exclude("fabric.mod.json", "META-INF/neoforge.mods.toml", "pack.mcmeta") + } + register("buildAndCollect") { + group = "build" + from(named("remapJar"), named("remapSourcesJar")) + into(rootProject.layout.buildDirectory.file("libs/$modVersion/forge")) + } +} + +val modrinthToken = providers.environmentVariable("MODRINTH_API_KEY") + .orElse(providers.systemProperty("MODRINTH_API_KEY")) +val curseforgeToken = providers.environmentVariable("CURSEFORGE_TOKEN") + .orElse(providers.systemProperty("CURSEFORGE_TOKEN")) + +val mcReleases = (sc.properties.raw("mod", "mc_releases") as SCList) + .map { (it as SCPrimitive).content.toString() } + +publishMods { + file = tasks.named("remapJar").flatMap { it.archiveFile } + type = ReleaseType.STABLE + displayName = "Forge | $versionName [v$modVersion]" + version = project.version.toString() + changelog = rootProject.file("CHANGES.md").readText() + modLoaders.add("forge") + + dryRun = !project.hasProperty("publishRelease") + + modrinth { + accessToken = modrinthToken + projectId = "w4Xqquyv" + minecraftVersions.addAll(mcReleases) + requires("cloth-config") + } + + curseforge { + accessToken = curseforgeToken + projectId = "1421731" + minecraftVersions.addAll(mcReleases) + javaVersions.add(requiredJava) + client = true + server = false + changelogType = "markdown" + requires("cloth-config") + } +} diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 4c29a8a..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,217 +0,0 @@ -plugins { - id("dev.architectury.loom") - id("architectury-plugin") - id("me.modmuss50.mod-publish-plugin") - id("com.gradleup.shadow") -} - -val minecraft = stonecutter.current.version -val loader = loom.platform.get().name.lowercase() - -version = "${mod.version}+${mod.prop("version_name")}-$loader" -group = mod.group -base { - archivesName.set(mod.id) -} - -val isFabric = loader == "fabric" -val isForge = loader == "forge" -val isNeoForge = loader == "neoforge" - -stonecutter.const("fabric", isFabric) -stonecutter.const("forge", isForge) -stonecutter.const("neoforge", isNeoForge) - -architectury.common(stonecutter.tree.branches.mapNotNull { - if (stonecutter.current.project !in it) null - else it.project.prop("loom.platform") -}) -repositories { - maven("https://maven.shedaniel.me/") - maven("https://maven.terraformersmc.com/releases/") - maven("https://maven.neoforged.net/releases") - maven("https://maven.minecraftforge.net") - -} -dependencies { - minecraft("com.mojang:minecraft:$minecraft") - mappings(loom.officialMojangMappings()) - - modImplementation("me.shedaniel.cloth:cloth-config-${loader}:${mod.dep("cloth_config_version")}") - - if (isFabric) { - modImplementation("net.fabricmc:fabric-loader:${mod.dep("fabric_loader")}") - modImplementation("com.terraformersmc:modmenu:${mod.dep("mod_menu_version")}") - } - if (isForge) { - "forge"("net.minecraftforge:forge:${minecraft}-${mod.dep("forge_loader")}") - } - if (isNeoForge) { - "neoForge"("net.neoforged:neoforge:${mod.dep("neoforge_loader")}") - } -} - -loom { - decompilers { - get("vineflower").apply { // Adds names to lambdas - useful for mixins - options.put("mark-corresponding-synthetics", "1") - } - } - - accessWidenerPath = rootProject.file("src/main/resources/xyzcopy.accesswidener") - - if (isForge) { - forge { - mixinConfig("xyzcopy.mixins.json") - - convertAccessWideners = true - extraAccessWideners.add(accessWidenerPath.get().asFile.name) - } - } - -} - -java { - withSourcesJar() - val javaVersion = mod.dep("java") - val java = when (javaVersion) { - "8" -> JavaVersion.VERSION_1_8 - "17" -> JavaVersion.VERSION_17 - "21" -> JavaVersion.VERSION_21 - "25" -> JavaVersion.VERSION_25 - else -> JavaVersion.VERSION_21 - } - targetCompatibility = java - sourceCompatibility = java -} - -val shadowBundle: Configuration by configurations.creating { - isCanBeConsumed = false - isCanBeResolved = true -} - -tasks.shadowJar { - configurations = listOf(shadowBundle) - archiveClassifier = "dev-shadow" -} - -tasks.remapJar { - injectAccessWidener = true - inputFile.set(tasks.shadowJar.get().archiveFile) - archiveClassifier = null - dependsOn(tasks.shadowJar) -} - -tasks.jar { - archiveClassifier = "dev" -} - -val buildAndCollect = tasks.register("buildAndCollect") { - group = "versioned" - description = "Must run through 'chiseledBuild'" - from(tasks.remapJar.get().archiveFile, tasks.remapSourcesJar.get().archiveFile) - into(rootProject.layout.buildDirectory.file("libs/${mod.version}/$loader")) - dependsOn("build") -} - -if (stonecutter.current.isActive) { - rootProject.tasks.register("buildActive") { - group = "project" - dependsOn(buildAndCollect) - } - - rootProject.tasks.register("runActive") { - group = "project" - dependsOn(tasks.named("runClient")) - } -} - -tasks.processResources { - var clothConfigSeparator = "_" - if(minecraft == "1.16.5") clothConfigSeparator = "-" - - val expandProps = mapOf( - "version" to version, - "minecraftVersion" to mod.prop("mc_dep"), - "javaVersion" to mod.dep("java"), - "cloth_config_separator" to clothConfigSeparator - ) - - if (isFabric) { - filesMatching("fabric.mod.json") { expand(expandProps) } - exclude("META-INF/mods.toml", "META-INF/neoforge.mods.toml", "pack.mcmeta") - } - - if(isForge || isNeoForge) { - filesMatching("META-INF/*mods.toml") { expand(expandProps) } - exclude("fabric.mod.json") - } - - inputs.properties(expandProps) - -} - -tasks.build { - group = "versioned" - description = "Must run through 'chiseledBuild'" -} - -publishMods { - version.set(project.version.toString()) - displayName.set("${loader.upperCaseFirst()} | ${mod.prop("version_name")} [v${mod.version}]") - type = STABLE - file.set(tasks.remapJar.get().archiveFile) - val mcVersions = mod.prop("mc_targets").split(",") - - changelog = rootProject.file("CHANGES.md").readText() - if(isFabric) changelog = "## [Fabric API](https://modrinth.com/mod/fabric-api) is required for Custom Keybinds!\n\n" + changelog.get() - - - modLoaders.add(loader) - if(isFabric) modLoaders.add("quilt") - - - modrinth { - accessToken = providers.environmentVariable("MODRINTH_API_KEY") - - projectId = "w4Xqquyv" - minecraftVersions.addAll(mcVersions) - - requires("cloth-config") - if(isFabric) { - optional("fabric-api") - optional("modmenu") - } - } - - curseforge { - accessToken = providers.environmentVariable("CURSEFORGE_TOKEN") - - projectId = "1421731" - minecraftVersions.addAll(mcVersions) - - val javaVersion = mod.dep("java") - val java = when (javaVersion) { - "8" -> JavaVersion.VERSION_1_8 - "17" -> JavaVersion.VERSION_17 - "21" -> JavaVersion.VERSION_21 - "25" -> JavaVersion.VERSION_25 - else -> JavaVersion.VERSION_21 - } - javaVersions.add(java) - - clientRequired = true - serverRequired = false - - changelogType = "markdown" - - requires("cloth-config") - if(isFabric) { - optional("fabric-api") - optional("modmenu") - } - } - - //TODO: remove this when actually want to release - dryRun = true -} \ No newline at end of file diff --git a/build.neoforge.gradle.kts b/build.neoforge.gradle.kts new file mode 100644 index 0000000..17d4cab --- /dev/null +++ b/build.neoforge.gradle.kts @@ -0,0 +1,137 @@ +import dev.kikugie.stonecutter.data.deserialization.SCList +import dev.kikugie.stonecutter.data.deserialization.SCPrimitive +import me.modmuss50.mpp.ReleaseType + +plugins { + alias(libs.plugins.neoforge.moddev) + id("neoforge-mutex") + alias(libs.plugins.mod.publish) +} + +val modVersion = property("mod.version") as String +val modId = property("mod.id") as String +val mcCompat = property("mod.mc_compat") as String +val versionName = property("mod.version_name") as String + +version = "$modVersion+$versionName-neoforge" +group = property("mod.group") as String +base.archivesName = modId + +val requiredJava: JavaVersion = when { + sc.current.parsed >= "26.1" -> JavaVersion.VERSION_25 + sc.current.parsed >= "1.20.5" -> JavaVersion.VERSION_21 + else -> JavaVersion.VERSION_17 +} + +repositories { + maven("https://maven.shedaniel.me/") +} + +dependencies { + implementation("me.shedaniel.cloth:cloth-config-neoforge:${property("deps.cloth_config")}") +} + +neoForge { + version = property("deps.neo_loader") as String + + mods { + register(modId) { + sourceSet(sourceSets.main.get()) + } + } + + runs { + register("client") { gameDirectory = rootProject.file("run"); client() } + } +} + +java { + withSourcesJar() + toolchain { + vendor = JvmVendorSpec.ADOPTIUM + languageVersion = JavaLanguageVersion.of(25) + } +} + +tasks.withType().configureEach { + options.release = requiredJava.majorVersion.toInt() +} + +val runLauncher = extensions.getByType().launcherFor { + languageVersion = JavaLanguageVersion.of(requiredJava.majorVersion) + vendor = JvmVendorSpec.ADOPTIUM +} +// older versions dont like being ran with java 25 +tasks.withType().matching { it.name.startsWith("run") }.configureEach { + javaLauncher = runLauncher +} + +val java25 = extensions.getByType().launcherFor { + languageVersion = JavaLanguageVersion.of(25) + vendor = JvmVendorSpec.ADOPTIUM +} +tasks.withType().configureEach { + toolsJavaExecutable = java25.map { it.executablePath.asFile.absolutePath } +} + + +tasks { + processResources { + val mixinJava = "JAVA_${requiredJava.majorVersion}" + val props = mapOf( + "version" to modVersion, + "minecraftVersion" to mcCompat, + "javaVersion" to requiredJava.majorVersion, + "cloth_config_separator" to "_" + ) + props.forEach { (k, v) -> inputs.property(k, v) } + filesMatching("META-INF/neoforge.mods.toml") { expand(props) } + filesMatching("*.mixins.json") { expand("java" to mixinJava) } + exclude("fabric.mod.json", "META-INF/mods.toml") + } + + named("createMinecraftArtifacts") { dependsOn("stonecutterGenerate") } + + register("buildAndCollect") { + group = "build" + from(named("jar").flatMap { it.archiveFile }, named("sourcesJar").flatMap { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/$modVersion/neoforge")) + } +} + +val modrinthToken = providers.environmentVariable("MODRINTH_API_KEY") + .orElse(providers.systemProperty("MODRINTH_API_KEY")) +val curseforgeToken = providers.environmentVariable("CURSEFORGE_TOKEN") + .orElse(providers.systemProperty("CURSEFORGE_TOKEN")) + +val mcReleases = (sc.properties.raw("mod", "mc_releases") as SCList) + .map { (it as SCPrimitive).content.toString() } + +publishMods { + file = tasks.named("jar").flatMap { it.archiveFile } + type = ReleaseType.STABLE + displayName = "NeoForge | $versionName [v$modVersion]" + version = project.version.toString() + changelog = rootProject.file("CHANGES.md").readText() + modLoaders.add("neoforge") + + dryRun = !project.hasProperty("publishRelease") + + modrinth { + accessToken = modrinthToken + projectId = "w4Xqquyv" + minecraftVersions.addAll(mcReleases) + requires("cloth-config") + } + + curseforge { + accessToken = curseforgeToken + projectId = "1421731" + minecraftVersions.addAll(mcReleases) + javaVersions.add(requiredJava) + client = true + server = false + changelogType = "markdown" + requires("cloth-config") + } +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index c7082a3..f129248 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,8 +1,15 @@ plugins { `kotlin-dsl` - kotlin("jvm") version "2.1.10" } - repositories { + gradlePluginPortal() mavenCentral() -} \ No newline at end of file +} +gradlePlugin { + plugins { + register("loom-plugin-chooser") { + id = "loom-plugin-chooser" + implementationClass = "LoomPluginChooser" + } + } +} diff --git a/buildSrc/src/main/kotlin/LoomPluginChooser.kt b/buildSrc/src/main/kotlin/LoomPluginChooser.kt new file mode 100644 index 0000000..507c0b1 --- /dev/null +++ b/buildSrc/src/main/kotlin/LoomPluginChooser.kt @@ -0,0 +1,28 @@ +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.extra + +// loom.platform must be set before the Loom plugin applies (the only reliably-early +// point); 26.x is unobfuscated so it uses loom-no-remap with mod* configs recreated. +open class LoomPluginChooser : Plugin { + override fun apply(target: Project): Unit = with(target) { + val loader = name.substringAfterLast('-') + if (loader != "fabric") extra.set("loom.platform", loader) + + val obfuscated = name.substringBefore('-').startsWith("1.") + if (obfuscated) { + plugins.apply("dev.architectury.loom") + } else { + plugins.apply("dev.architectury.loom-no-remap") + for (cfg in listOf("api", "implementation", "compileOnly", "runtimeOnly", "localRuntime")) { + val loomified = "mod" + cfg.replaceFirstChar(Char::uppercaseChar) + val new = configurations.create(loomified) + configurations.named(cfg) { extendsFrom(new) } + } + configurations.register("mappings") { + isCanBeResolved = false + isCanBeConsumed = false + } + } + } +} diff --git a/buildSrc/src/main/kotlin/build-extensions.kt b/buildSrc/src/main/kotlin/build-extensions.kt deleted file mode 100644 index 6f27ab9..0000000 --- a/buildSrc/src/main/kotlin/build-extensions.kt +++ /dev/null @@ -1,31 +0,0 @@ -import org.gradle.api.Project -import org.gradle.api.artifacts.dsl.RepositoryHandler -import org.gradle.kotlin.dsl.maven -import org.gradle.language.jvm.tasks.ProcessResources - -val Project.mod: ModData get() = ModData(this) -fun Project.prop(key: String): String? = findProperty(key)?.toString() -fun String.upperCaseFirst() = replaceFirstChar { if (it.isLowerCase()) it.uppercaseChar() else it } - -fun RepositoryHandler.strictMaven(url: String, alias: String, vararg groups: String) = exclusiveContent { - forRepository { maven(url) { name = alias } } - filter { groups.forEach(::includeGroup) } -} - -fun ProcessResources.properties(files: Iterable, vararg properties: Pair) { - for ((name, value) in properties) inputs.property(name, value) - filesMatching(files) { - expand(properties.toMap()) - } -} - -@JvmInline -value class ModData(private val project: Project) { - val id: String get() = requireNotNull(project.prop("mod.id")) { "Missing 'mod.id'" } - val name: String get() = requireNotNull(project.prop("mod.name")) { "Missing 'mod.name'" } - val version: String get() = requireNotNull(project.prop("mod.version")) { "Missing 'mod.version'" } - val group: String get() = requireNotNull(project.prop("mod.group")) { "Missing 'mod.group'" } - - fun prop(key: String) = requireNotNull(project.prop("mod.$key")) { "Missing 'mod.$key'" } - fun dep(key: String) = requireNotNull(project.prop("deps.$key")) { "Missing 'deps.$key'" } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/neoforge-mutex.gradle.kts b/buildSrc/src/main/kotlin/neoforge-mutex.gradle.kts new file mode 100644 index 0000000..29bc7f4 --- /dev/null +++ b/buildSrc/src/main/kotlin/neoforge-mutex.gradle.kts @@ -0,0 +1,13 @@ +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters + +// Serializes NeoForge's Minecraft artifact creation so building many versions doesn't recompile MC in parallel. +interface NeoForgeMutex : BuildService + +val mutex = gradle.sharedServices.registerIfAbsent("createMinecraftArtifactsMutex", NeoForgeMutex::class.java) { + maxParallelUsages.set(1) +} + +tasks.named { it == "createMinecraftArtifacts" }.configureEach { + usesService(mutex) +} diff --git a/gradle.properties b/gradle.properties index 3ebdac7..0d9441a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,33 +1,3 @@ -# Done to increase the memory available to Gradle. org.gradle.jvmargs=-Xmx4G -#org.gradle.parallel=true -org.gradle.caching=false -org.gradle.caching.debug=false -org.gradle.parallel=false -#org.gradle.configureondemand=true - -# Mod properties -mod.version=1.0.0 -mod.group=net.notcoded -mod.id=xyzcopy -mod.name=XYZ Copy - -# Used for the mod metadata -mod.mc_dep=[VERSIONED] -# Used for the release title. I.e. '1.20.x' -mod.version_name=[VERSIONED] -# Space separated versions for publishing. I.e. '1.20, 1.20.1' -mod.mc_targets=[VERSIONED] - -# Mod setup -deps.mixin_extras=0.4.1 -deps.fabric_loader=0.14.20 -deps.fabric_version=[VERSIONED] - -deps.forge_loader=[VERSIONED] -deps.neoforge_loader=[VERSIONED] - -# Mod dependencies -deps.mod_menu_version=[VERSIONED] -deps.cloth_config_version=[VERSIONED] -deps.java=[VERSIONED] +org.gradle.parallel=true +org.gradle.configuration-cache=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..aaf0d37 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +# Stonecutter and the foojay resolver are declared in settings.gradle.kts instead — +# Gradle can't resolve catalog accessors inside a settings `plugins {}` block. +[versions] +architectury-loom = "1.17-SNAPSHOT" +neoforge-moddev = "2.0.140" +mod-publish = "2.1.1" + +[plugins] +architectury-loom = { id = "dev.architectury.loom", version.ref = "architectury-loom" } +architectury-loom-no-remap = { id = "dev.architectury.loom-no-remap", version.ref = "architectury-loom" } +neoforge-moddev = { id = "net.neoforged.moddev", version.ref = "neoforge-moddev" } +mod-publish = { id = "me.modmuss50.mod-publish-plugin", version.ref = "mod-publish" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baabb587c669f562ae36f953de2481846..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 40183 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 delta 35506 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 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 +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,30 +65,18 @@ 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 +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH= -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -: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 +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/settings.gradle.kts b/settings.gradle.kts index 17c957b..99918eb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,34 +3,43 @@ pluginManagement { mavenCentral() gradlePluginPortal() maven("https://maven.fabricmc.net/") - maven("https://maven.architectury.dev") - maven("https://maven.minecraftforge.net") maven("https://maven.neoforged.net/releases/") + maven("https://maven.minecraftforge.net") + maven("https://maven.architectury.dev") + maven("https://maven.kikugie.dev/releases") maven("https://maven.kikugie.dev/snapshots") + maven("https://maven.parchmentmc.org") } } plugins { - id("dev.kikugie.stonecutter") version "0.6.1" + id("dev.kikugie.stonecutter") version "0.9.6" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } stonecutter { - centralScript = "build.gradle.kts" - kotlinController = true - shared { - fun mc(loader: String, vararg versions: String) { - for (version in versions) vers("$version-$loader", version) + create(rootProject) { + fun match(project: String, vararg loaders: String, version: String = project) { + for (loader in loaders) version("$project-$loader", version).buildscript("build.$loader.gradle.kts") } - - // TODO: 26.1 (requires seperate build script) - mc("fabric", "1.16.5", "1.17.1", "1.19", "1.19.4", "1.20.1", "1.21.9", "1.21.11") - mc("forge", "1.16.5", "1.17.1", "1.18.2", "1.19", "1.19.4", "1.20.1", "1.20.6", "1.21.6", "1.21.9", "1.21.11") - mc("neoforge", "1.20.4", "1.20.6", "1.21.9", "1.21.11") + match("1.16.5", "fabric", "forge") + match("1.17.1", "fabric", "forge") + match("1.18.2", "forge") + match("1.19", "fabric", "forge") + match("1.19.4", "fabric", "forge") + match("1.20.1", "fabric", "forge") + match("1.21.6", "forge") + match("1.20.4", "neoforge") + match("1.20.6", "neoforge", "forge") + match("1.21.9", "fabric", "neoforge", "forge") + match("1.21.11", "fabric", "neoforge", "forge") + match("26.1", "fabric", "neoforge", "forge") + match("26.2", "fabric", "neoforge", "forge") vcsVersion = "1.16.5-fabric" } - create(rootProject) } -rootProject.name = "xyzcopy" \ No newline at end of file +rootProject.name = "xyzcopy" + diff --git a/src/main/java/net/notcoded/xyzcopy/XYZCopy.java b/src/main/java/net/notcoded/xyzcopy/XYZCopy.java index 03dd4f3..61dd2bf 100644 --- a/src/main/java/net/notcoded/xyzcopy/XYZCopy.java +++ b/src/main/java/net/notcoded/xyzcopy/XYZCopy.java @@ -7,8 +7,8 @@ //? if 1.21.9 { //import net.minecraft.resources.ResourceLocation; //?} elif >=1.21.11 { -/*import net.minecraft.resources.Identifier; -*///?} +import net.minecraft.resources.Identifier; +//?} import net.notcoded.xyzcopy.config.ModClothConfig; import net.notcoded.xyzcopy.config.ModConfig; import net.notcoded.xyzcopy.platforms.ModPlatform; @@ -22,17 +22,17 @@ public class XYZCopy { public static ModPlatform platform; //? if >=1.21.9 { - /*public static final KeyMapping.Category category = new KeyMapping.Category( + public static final KeyMapping.Category category = new KeyMapping.Category( //? if 1.21.9 { //ResourceLocation //?} elif >=1.21.11 { - /^Identifier - ^///?} + Identifier + //?} .fromNamespaceAndPath("xyzcopy", "keybind") ); - *///?} else { - private static final String category = "key.category.xyzcopy.keybind"; - //?} + //?} else { + /*private static final String category = "key.category.xyzcopy.keybind"; + *///?} public static KeyMapping openConfigKeybind = new KeyMapping("xyzcopy.keybind.open_config", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, category); diff --git a/src/main/java/net/notcoded/xyzcopy/mixin/KeyMappingAccessor.java b/src/main/java/net/notcoded/xyzcopy/mixin/KeyMappingAccessor.java new file mode 100644 index 0000000..6d227d9 --- /dev/null +++ b/src/main/java/net/notcoded/xyzcopy/mixin/KeyMappingAccessor.java @@ -0,0 +1,12 @@ +package net.notcoded.xyzcopy.mixin; + +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyMapping; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(KeyMapping.class) +public interface KeyMappingAccessor { + @Accessor("key") + InputConstants.Key getKey(); +} diff --git a/src/main/java/net/notcoded/xyzcopy/mixin/KeyboardHandlerMixin.java b/src/main/java/net/notcoded/xyzcopy/mixin/KeyboardHandlerMixin.java index 0aa387a..e042d4a 100644 --- a/src/main/java/net/notcoded/xyzcopy/mixin/KeyboardHandlerMixin.java +++ b/src/main/java/net/notcoded/xyzcopy/mixin/KeyboardHandlerMixin.java @@ -3,16 +3,16 @@ import net.minecraft.client.KeyboardHandler; //? if >=1.21.9 { -/*import net.minecraft.client.Minecraft; +import net.minecraft.client.Minecraft; import net.minecraft.client.input.KeyEvent; -*///?} +//?} //? if >=1.21.11 { -/*import net.minecraft.util.Util; -*///?} else { -import net.minecraft.Util; +import net.minecraft.util.Util; +//?} else { +/*import net.minecraft.Util; import org.lwjgl.glfw.GLFW; -//?} +*///?} import net.notcoded.xyzcopy.XYZCopy; import net.notcoded.xyzcopy.config.ModConfig; import net.notcoded.xyzcopy.util.LocationUtil; @@ -29,33 +29,33 @@ public abstract class KeyboardHandlerMixin { private long debugCrashKeyTime; //? if <1.21.9 { - @Inject(method = "handleDebugKeys", at = @At("HEAD"), cancellable = true) - private void debugKey(int i, CallbackInfoReturnable cir) { - //?} elif >=1.21.9 { /*@Inject(method = "handleDebugKeys", at = @At("HEAD"), cancellable = true) + private void debugKey(int i, CallbackInfoReturnable cir) { + *///?} elif >=1.21.9 { + @Inject(method = "handleDebugKeys", at = @At("HEAD"), cancellable = true) private void debugKey(KeyEvent arg, CallbackInfoReturnable cir) { int i = arg.key(); - *///?} + //?} if (this.debugCrashKeyTime > 0L && this.debugCrashKeyTime < Util.getMillis() - 100L) return; ModConfig config = XYZCopy.config; - if(XYZCopy.config.location.useKeybindWithF3 && i == XYZCopy.copyLocationKeybind.key.getValue()) { + if(config.location.useKeybindWithF3 && i == ((KeyMappingAccessor) XYZCopy.copyLocationKeybind).getKey().getValue()) { cir.setReturnValue(true); LocationUtil.copyLocation(); return; } - if(XYZCopy.config.block.useKeybindWithF3 && i == XYZCopy.copyBlockKeybind.key.getValue()) { + if(config.block.useKeybindWithF3 && i == ((KeyMappingAccessor) XYZCopy.copyBlockKeybind).getKey().getValue()) { cir.setReturnValue(true); LocationUtil.copyBlockLocation(); return; } //? if >=1.21.11 { - /*boolean f3CKey = Minecraft.getInstance().options.keyDebugCopyLocation.matches(arg); - *///?} else { - boolean f3CKey = i == GLFW.GLFW_KEY_C; - //?} + boolean f3CKey = Minecraft.getInstance().options.keyDebugCopyLocation.matches(arg); + //?} else { + /*boolean f3CKey = i == GLFW.GLFW_KEY_C; + *///?} if(f3CKey && config.location.replaceDebugKey) { cir.setReturnValue(true); diff --git a/src/main/java/net/notcoded/xyzcopy/mixin/MinecraftMixin.java b/src/main/java/net/notcoded/xyzcopy/mixin/MinecraftMixin.java index 67c22a3..aeb7c97 100644 --- a/src/main/java/net/notcoded/xyzcopy/mixin/MinecraftMixin.java +++ b/src/main/java/net/notcoded/xyzcopy/mixin/MinecraftMixin.java @@ -27,7 +27,11 @@ private void tick(CallbackInfo ci) { } while(XYZCopy.openConfigKeybind.consumeClick()) { + //? if >=26.2 { + /*Minecraft.getInstance().gui.setScreen(ModClothConfig.buildScreen(Minecraft.getInstance().gui.screen())); + *///?} else { Minecraft.getInstance().setScreen(ModClothConfig.buildScreen(Minecraft.getInstance().screen)); + //?} } } } diff --git a/src/main/java/net/notcoded/xyzcopy/platforms/fabric/XYZCopyFabric.java b/src/main/java/net/notcoded/xyzcopy/platforms/fabric/XYZCopyFabric.java index 68f6499..268b853 100644 --- a/src/main/java/net/notcoded/xyzcopy/platforms/fabric/XYZCopyFabric.java +++ b/src/main/java/net/notcoded/xyzcopy/platforms/fabric/XYZCopyFabric.java @@ -2,8 +2,11 @@ package net.notcoded.xyzcopy.platforms.fabric; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl; +//? if >=26.1 { +import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper; +//?} else { +/*import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +*///?} import net.fabricmc.loader.api.FabricLoader; import net.notcoded.xyzcopy.XYZCopy; import net.notcoded.xyzcopy.platforms.ModPlatform; @@ -12,11 +15,19 @@ public class XYZCopyFabric implements ClientModInitializer { @Override public void onInitializeClient() { - if(FabricLoader.getInstance().isModLoaded("fabric-key-binding-api-v1")) { + //? if >=26.1 { + if(FabricLoader.getInstance().isModLoaded("fabric-key-mapping-api-v1")) { + XYZCopy.openConfigKeybind = KeyMappingHelper.registerKeyMapping(XYZCopy.openConfigKeybind); + XYZCopy.copyBlockKeybind = KeyMappingHelper.registerKeyMapping(XYZCopy.copyBlockKeybind); + XYZCopy.copyLocationKeybind = KeyMappingHelper.registerKeyMapping(XYZCopy.copyLocationKeybind); + } + //?} else { + /*if(FabricLoader.getInstance().isModLoaded("fabric-key-binding-api-v1")) { XYZCopy.openConfigKeybind = KeyBindingHelper.registerKeyBinding(XYZCopy.openConfigKeybind); XYZCopy.copyBlockKeybind = KeyBindingHelper.registerKeyBinding(XYZCopy.copyBlockKeybind); XYZCopy.copyLocationKeybind = KeyBindingHelper.registerKeyBinding(XYZCopy.copyLocationKeybind); } + *///?} XYZCopy.init(new FabricPlatform()); } diff --git a/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java b/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java index 3561c9d..bf38b57 100644 --- a/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java +++ b/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java @@ -43,25 +43,54 @@ @Mod("xyzcopy") @OnlyIn(Dist.CLIENT) public class XYZCopyForge { - //? if <1.20.6 { + private static ModLoadingContext modLoadingContext; + + // Forge only injects the loading context into the mod constructor on 1.19.4 and 1.20.6+. + // On 1.19/1.20.1 it looks up a no-arg constructor, so the deprecated get() is the only option there. + //? if <1.19.4 { /^public XYZCopyForge() { + modLoadingContext = ModLoadingContext.get(); IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); modEventBus.addListener(XYZCopyForge::onClientSetup); //? if >=1.19 { modEventBus.addListener(XYZCopyForge::registerBindings); //?} } - ^///?} elif >=1.20.6 <1.21.6 { - /^public XYZCopyForge(IEventBus modEventBus) { + ^///?} elif <1.20 { + /^public XYZCopyForge(FMLJavaModLoadingContext context) { + modLoadingContext = context; + IEventBus modEventBus = context.getModEventBus(); modEventBus.addListener(XYZCopyForge::onClientSetup); modEventBus.addListener(XYZCopyForge::registerBindings); } - ^///?} elif >=1.21.6 { - public XYZCopyForge(FMLJavaModLoadingContext context) { + ^///?} elif <1.20.6 { + /^public XYZCopyForge() { + modLoadingContext = ModLoadingContext.get(); + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + modEventBus.addListener(XYZCopyForge::onClientSetup); + modEventBus.addListener(XYZCopyForge::registerBindings); + } + ^///?} elif <1.21.6 { + /^public XYZCopyForge(FMLJavaModLoadingContext context) { + modLoadingContext = context; + IEventBus modEventBus = context.getModEventBus(); + modEventBus.addListener(XYZCopyForge::onClientSetup); + modEventBus.addListener(XYZCopyForge::registerBindings); + } + ^///?} elif <1.21.9 { + /^public XYZCopyForge(FMLJavaModLoadingContext context) { + modLoadingContext = context; BusGroup modBusGroup = context.getModBusGroup(); FMLClientSetupEvent.getBus(modBusGroup).addListener(XYZCopyForge::onClientSetup); RegisterKeyMappingsEvent.getBus(modBusGroup).addListener(XYZCopyForge::registerBindings); } + ^///?} else { + public XYZCopyForge(FMLJavaModLoadingContext context) { + modLoadingContext = context; + BusGroup modBusGroup = context.getModBusGroup(); + FMLClientSetupEvent.getBus(modBusGroup).addListener(XYZCopyForge::onClientSetup); + RegisterKeyMappingsEvent.BUS.addListener(XYZCopyForge::registerBindings); + } //?} public static void onClientSetup(final FMLClientSetupEvent event) { @@ -105,19 +134,20 @@ public boolean isDevelopmentEnvironment() { static void setupConfigScreen() { //? if >=1.19 { - ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> + modLoadingContext.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory( (client, parent) -> ModClothConfig.buildScreen(parent) ) ); //?} elif >1.16.5 <1.19 { - /^ModLoadingContext.get().registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class, () -> + /^modLoadingContext.registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class, () -> new ConfigGuiHandler.ConfigGuiFactory((client, parent) -> ModClothConfig.buildScreen(parent) )); ^///?} elif 1.16.5 { - /^ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> + /^modLoadingContext.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (client, parent) -> ModClothConfig.buildScreen(parent) ); ^///?} } -}*/ \ No newline at end of file +} +*///?} diff --git a/src/main/java/net/notcoded/xyzcopy/util/LocationUtil.java b/src/main/java/net/notcoded/xyzcopy/util/LocationUtil.java index c63cd7c..04fcb15 100644 --- a/src/main/java/net/notcoded/xyzcopy/util/LocationUtil.java +++ b/src/main/java/net/notcoded/xyzcopy/util/LocationUtil.java @@ -2,10 +2,10 @@ import net.minecraft.client.Minecraft; //? if <1.19.4 { -import net.minecraft.core.Registry; -//?} elif >=1.19.4 { -/*import net.minecraft.core.registries.BuiltInRegistries; -*///?} +/*import net.minecraft.core.Registry; +*///?} elif >=1.19.4 { +import net.minecraft.core.registries.BuiltInRegistries; +//?} import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.BlockHitResult; @@ -37,20 +37,14 @@ public static void copyLocation() { .replace("%dimension", VersionUtil.getLevel(client.player).dimension() //? if >=1.21.11 { - /*.identifier() - *///?} else { - .location() - //?} + .identifier() + //?} else { + /*.location() + *///?} .toString() ); - if(sendInChat) { - client.gui.getChat().addMessage(VersionUtil.getTranslatableText(config.location.copyMessage.replaceAll("&", "§"))); - client.gui.getChat().addMessage(VersionUtil.getTranslatableText(locationTemplate)); - } else { - client.gui.getChat().addMessage(VersionUtil.getTranslatableText(config.location.copyMessageClipboard.replaceAll("&", "§"))); - client.keyboardHandler.setClipboard(locationTemplate); - } + handleLocation(config.location.copyMessage, config.location.copyMessageClipboard, locationTemplate, sendInChat); } public static void copyBlockLocation() { @@ -72,19 +66,19 @@ public static void copyBlockLocation() { if(XYZCopy.config.block.includeFluids) { FluidState fluidState = VersionUtil.getLevel(client.player).getFluidState(hitResult.getBlockPos()); //? if <1.19.4 { - block = String.valueOf(Registry.FLUID.getKey(fluidState.getType())); - //?} elif >=1.19.4 { - /*block = String.valueOf(BuiltInRegistries.FLUID.getKey(fluidState.getType())); - *///?} + /*block = String.valueOf(Registry.FLUID.getKey(fluidState.getType())); + *///?} elif >=1.19.4 { + block = String.valueOf(BuiltInRegistries.FLUID.getKey(fluidState.getType())); + //?} } if(block == null || block.equals("minecraft:empty")) { BlockState blockState = VersionUtil.getLevel(client.player).getBlockState(hitResult.getBlockPos()); //? if <1.19.4 { - block = String.valueOf(Registry.BLOCK.getKey(blockState.getBlock())); - //?} elif >=1.19.4 { - /*block = String.valueOf(BuiltInRegistries.BLOCK.getKey(blockState.getBlock())); - *///?} + /*block = String.valueOf(Registry.BLOCK.getKey(blockState.getBlock())); + *///?} elif >=1.19.4 { + block = String.valueOf(BuiltInRegistries.BLOCK.getKey(blockState.getBlock())); + //?} } String locationTemplate = config.block.locationTemplate @@ -94,19 +88,24 @@ public static void copyBlockLocation() { .replace("%block", block) .replace("%dimension", VersionUtil.getLevel(client.player).dimension() //? if >=1.21.11 { - /*.identifier() - *///?} else { - .location() - //?} + .identifier() + //?} else { + /*.location() + *///?} .toString() ); + handleLocation(config.block.copyMessage, config.block.copyMessageClipboard, locationTemplate, sendInChat); + } + + private static void handleLocation(String copyMessage, String clipboardMessage, String location, boolean sendInChat) { + Minecraft client = Minecraft.getInstance(); if(sendInChat) { - client.gui.getChat().addMessage(VersionUtil.getTranslatableText(config.block.copyMessage.replaceAll("&", "§"))); - client.gui.getChat().addMessage(VersionUtil.getTranslatableText(locationTemplate)); + VersionUtil.sendChatMessage(VersionUtil.getTranslatableText(copyMessage.replace("&", "§"))); + VersionUtil.sendChatMessage(VersionUtil.getTranslatableText(location)); } else { - client.gui.getChat().addMessage(VersionUtil.getTranslatableText(config.block.copyMessageClipboard.replaceAll("&", "§"))); - client.keyboardHandler.setClipboard(locationTemplate); + VersionUtil.sendChatMessage(VersionUtil.getTranslatableText(clipboardMessage.replace("&", "§"))); + client.keyboardHandler.setClipboard(location); } } } diff --git a/src/main/java/net/notcoded/xyzcopy/util/VersionUtil.java b/src/main/java/net/notcoded/xyzcopy/util/VersionUtil.java index 56ebae4..338e359 100644 --- a/src/main/java/net/notcoded/xyzcopy/util/VersionUtil.java +++ b/src/main/java/net/notcoded/xyzcopy/util/VersionUtil.java @@ -5,39 +5,50 @@ import net.minecraft.world.level.Level; //? if <1.19 { -import net.minecraft.network.chat.TranslatableComponent; -//?} +/*import net.minecraft.network.chat.TranslatableComponent; +*///?} public class VersionUtil { + + public static void sendChatMessage(Component message) { + net.minecraft.client.Minecraft client = net.minecraft.client.Minecraft.getInstance(); + //? if >=26.2 { + /*client.gui.chatListener().handleSystemMessage(message, false); + *///?} elif >=26.1 { + client.getChatListener().handleSystemMessage(message, false); + //?} else { + /*client.gui.getChat().addMessage(message); + *///?} + } public static float getYRot(LocalPlayer player) { //? if 1.16.5 { - return player.yRot; - //?} elif >1.16.5 { - /*return player.getYRot(); - *///?} + /*return player.yRot; + *///?} elif >1.16.5 { + return player.getYRot(); + //?} } public static float getXRot(LocalPlayer player) { //? if 1.16.5 { - return player.xRot; - //?} elif >1.16.5 { - /*return player.getXRot(); - *///?} + /*return player.xRot; + *///?} elif >1.16.5 { + return player.getXRot(); + //?} } public static Level getLevel(LocalPlayer player) { //? if >=1.20 { - /*return player.level(); - *///?} elif <1.20 { - return player.level; - //?} + return player.level(); + //?} elif <1.20 { + /*return player.level; + *///?} } public static Component getTranslatableText(String key) { //? if >=1.19 { - /*return Component.translatable(key); - *///?} elif <1.19 { - return new TranslatableComponent(key); - //?} + return Component.translatable(key); + //?} elif <1.19 { + /*return new TranslatableComponent(key); + *///?} } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b2c16f3..785ad32 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -38,6 +38,6 @@ }, "recommends": { "modmenu": "*", - "fabric-key-binding-api-v1": "*" + "${keyBindingApi}": "*" } -} \ No newline at end of file +} diff --git a/src/main/resources/xyzcopy.accesswidener b/src/main/resources/xyzcopy.accesswidener deleted file mode 100644 index f9cb8ba..0000000 --- a/src/main/resources/xyzcopy.accesswidener +++ /dev/null @@ -1,2 +0,0 @@ -accessWidener v1 named -accessible field net/minecraft/client/KeyMapping key Lcom/mojang/blaze3d/platform/InputConstants$Key; \ No newline at end of file diff --git a/src/main/resources/xyzcopy.mixins.json b/src/main/resources/xyzcopy.mixins.json index 64dda16..abb8dc6 100644 --- a/src/main/resources/xyzcopy.mixins.json +++ b/src/main/resources/xyzcopy.mixins.json @@ -2,10 +2,11 @@ "required": true, "minVersion": "0.8", "package": "net.notcoded.xyzcopy.mixin", - "compatibilityLevel": "JAVA_8", + "compatibilityLevel": "${java}", "client": [ "KeyboardHandlerMixin", - "MinecraftMixin" + "MinecraftMixin", + "KeyMappingAccessor" ], "injectors": { "defaultRequire": 1 diff --git a/stonecutter.gradle.kts b/stonecutter.gradle.kts index dabcf3f..dd45599 100644 --- a/stonecutter.gradle.kts +++ b/stonecutter.gradle.kts @@ -1,49 +1,31 @@ plugins { id("dev.kikugie.stonecutter") - id("dev.architectury.loom") version "1.14-SNAPSHOT" apply false - id("architectury-plugin") version "3.5-SNAPSHOT" apply false - id("com.gradleup.shadow") version "9.4.1" apply false - id("me.modmuss50.mod-publish-plugin") version "1.1.0" apply false + alias(libs.plugins.architectury.loom).apply(false) + alias(libs.plugins.architectury.loom.no.remap).apply(false) } -stonecutter active "1.16.5-fabric" /* [SC] DO NOT EDIT */ -// Builds every version into `build/libs/{mod.version}/{loader}` -stonecutter registerChiseled tasks.register("chiseledBuild", stonecutter.chiseled) { - group = "project" - ofTask("buildAndCollect") -} -stonecutter registerChiseled tasks.register("chiseledPublishMods", stonecutter.chiseled) { - group = "project" - ofTask("publishMods") -} -stonecutter registerChiseled tasks.register("chiseledRunAllClients", stonecutter.chiseled) { - group = "project" - ofTask("runClient") -} +stonecutter active file(".sc_active_version") +stonecutter parameters { + val (version, loader) = current.project.split('-', limit = 2) + properties { + tags(version, loader) + } -// Builds loader-specific versions into `build/libs/{mod.version}/{loader}` -for (it in stonecutter.tree.branches) { - if (it.id.isEmpty()) continue - val loader = it.id.upperCaseFirst() - stonecutter registerChiseled tasks.register("chiseledBuild$loader", stonecutter.chiseled) { - group = "project" - versions { branch, _ -> branch == it.id } - ofTask("buildAndCollect") + constants { + match(loader, "fabric", "forge", "neoforge") } } -/* -// Runs active versions for each loader -for (it in stonecutter.tree.nodes) { - if (it.metadata != stonecutter.current || it.branch.id.isEmpty()) continue - val types = listOf("Client", "Server") - val loader = it.branch.id.upperCaseFirst() - for (type in types) it.tasks.register("runActive$type$loader") { - group = "project" - dependsOn("run$type") - } +// there is no chiseledBuild task anymore +tasks.register("chiseledBuild") { + group = "project" + dependsOn(stonecutter.tasks.named("buildAndCollect").map { it.values }) } - */ +// Runs as a Dry run unless -PpublishRelease is specified +tasks.register("chiseledPublish") { + group = "publishing" + dependsOn(stonecutter.tasks.named("publishMods").map { it.values }) +} diff --git a/stonecutter.properties.toml b/stonecutter.properties.toml new file mode 100644 index 0000000..9818377 --- /dev/null +++ b/stonecutter.properties.toml @@ -0,0 +1,197 @@ +mod.id = "xyzcopy" +mod.name = "XYZ Copy" +mod.group = "net.notcoded" +mod.version = "1.0.1" + +deps.fabric_loader = "0.18.6" + +[fabric."1.16.5"] +mod.version_name = "1.16.x" +mod.mc_compat = "1.16.x" +mod.mc_releases = ["1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5"] +deps.cloth_config = "4.17.101" +deps.mod_menu = "1.16.23" +deps.fabric_api = "0.42.0+1.16" + +[fabric."1.17.1"] +mod.version_name = "1.17-1.18.2" +mod.mc_compat = ">=1.17- <=1.18.2" +mod.mc_releases = ["1.17", "1.17.1", "1.18", "1.18.1", "1.18.2"] +deps.cloth_config = "5.3.63" +deps.mod_menu = "2.0.17" +deps.fabric_api = "0.46.1+1.17" + +[fabric."1.19"] +mod.version_name = "1.19-1.19.2" +mod.mc_compat = ">=1.19- <=1.19.2" +mod.mc_releases = ["1.19", "1.19.1", "1.19.2"] +deps.cloth_config = "8.3.134" +deps.mod_menu = "4.0.0" +deps.fabric_api = "0.58.0+1.19" + +[fabric."1.19.4"] +mod.version_name = "1.19.3-1.19.4" +mod.mc_compat = ">=1.19.3- <=1.19.4" +mod.mc_releases = ["1.19.3", "1.19.4"] +deps.cloth_config = "9.0.94" +deps.mod_menu = "5.1.0" +deps.fabric_api = "0.87.2+1.19.4" + +[fabric."1.20.1"] +mod.version_name = "1.20-1.21.8" +mod.mc_compat = ">=1.20- <=1.21.8" +mod.mc_releases = ["1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8"] +deps.cloth_config = "9.0.94" +deps.mod_menu = "5.1.0" +deps.fabric_api = "0.92.9+1.20.1" + +[fabric."1.21.9"] +mod.version_name = "1.21.9-1.21.10" +mod.mc_compat = ">=1.21.9- <=1.21.10" +mod.mc_releases = ["1.21.9", "1.21.10"] +deps.cloth_config = "17.0.144" +deps.mod_menu = "16.0.0" +deps.fabric_api = "0.134.1+1.21.9" + +[fabric."1.21.11"] +mod.version_name = "1.21.11" +mod.mc_compat = ">=1.21.11- <26.1" +mod.mc_releases = ["1.21.11"] +deps.cloth_config = "17.0.144" +deps.mod_menu = "16.0.0" +deps.fabric_api = "0.141.4+1.21.11" + +[fabric."26.1"] +mod.version_name = "26.1" +mod.mc_compat = ">=26.1- <26.2" +mod.mc_releases = ["26.1", "26.1.1", "26.1.2"] +deps.cloth_config = "26.1.154" +deps.mod_menu = "18.0.0-alpha.8" +deps.fabric_api = "0.145.1+26.1" + +[fabric."26.2"] +mod.version_name = "26.2" +mod.mc_compat = ">=26.2" +mod.mc_releases = ["26.2"] +deps.cloth_config = "26.2.155" +deps.mod_menu = "20.0.1" +deps.fabric_api = "0.155.2+26.2" + +[forge."1.16.5"] +mod.version_name = "1.16.x" +mod.mc_compat = "[1.16, 1.16.5]" +mod.mc_releases = ["1.16", "1.16.1", "1.16.2", "1.16.3", "1.16.4", "1.16.5"] +deps.cloth_config = "4.17.101" +deps.forge_loader = "36.2.34" + +[forge."1.17.1"] +mod.version_name = "1.17.x" +mod.mc_compat = "[1.17, 1.17.1]" +mod.mc_releases = ["1.17", "1.17.1"] +deps.cloth_config = "5.3.63" +deps.forge_loader = "37.1.1" + +[forge."1.18.2"] +mod.version_name = "1.18.x" +mod.mc_compat = "[1.18, 1.18.2]" +mod.mc_releases = ["1.18", "1.18.1", "1.18.2"] +deps.cloth_config = "6.5.102" +deps.forge_loader = "40.3.0" + +[forge."1.19"] +mod.version_name = "1.19-1.19.2" +mod.mc_compat = "[1.19, 1.19.1, 1.19.2]" +mod.mc_releases = ["1.19", "1.19.1", "1.19.2"] +deps.cloth_config = "8.3.134" +deps.forge_loader = "41.1.0" + +[forge."1.19.4"] +mod.version_name = "1.19.3-1.19.4" +mod.mc_compat = "[1.19.3, 1.19.4]" +mod.mc_releases = ["1.19.3", "1.19.4"] +deps.cloth_config = "9.0.94" +deps.forge_loader = "45.4.0" + +[forge."1.20.1"] +mod.version_name = "1.20-1.20.4" +mod.mc_compat = "[1.20, 1.20.4]" +mod.mc_releases = ["1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4"] +deps.cloth_config = "11.1.136" +deps.forge_loader = "47.3.0" + +[forge."1.20.6"] +mod.version_name = "1.20.5-1.21.5" +mod.mc_compat = "[1.20.5, 1.21.5]" +mod.mc_releases = ["1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5"] +deps.cloth_config = "14.0.139" +deps.forge_loader = "50.2.0" + +[forge."1.21.6"] +mod.version_name = "1.21.6-1.21.8" +mod.mc_compat = "[1.21.6, 1.21.8]" +mod.mc_releases = ["1.21.6", "1.21.7", "1.21.8"] +deps.cloth_config = "17.0.144" +deps.forge_loader = "56.0.2" + +[forge."1.21.9"] +mod.version_name = "1.21.9-1.21.10" +mod.mc_compat = "[1.21.9, 1.21.10]" +mod.mc_releases = ["1.21.9", "1.21.10"] +deps.cloth_config = "17.0.144" +deps.forge_loader = "59.0.5" + +[forge."1.21.11"] +mod.version_name = "1.21.11" +mod.mc_compat = "[1.21.11]" +mod.mc_releases = ["1.21.11"] +deps.cloth_config = "17.0.144" +deps.forge_loader = "61.1.0" + +[forge."26.1"] +mod.version_name = "26.1" +mod.mc_compat = "[26.1, 26.1.2]" +mod.mc_releases = ["26.1", "26.1.1", "26.1.2"] +deps.cloth_config = "26.1.154" +deps.forge_loader = "62.0.9" + +[neoforge."1.20.4"] +mod.version_name = "1.20.2-1.20.4" +mod.mc_compat = "[1.20.2, 1.20.4]" +mod.mc_releases = ["1.20.2", "1.20.3", "1.20.4"] +deps.cloth_config = "13.0.138" +deps.neo_loader = "20.4.251" + +[neoforge."1.20.6"] +mod.version_name = "1.20.5-1.21.8" +mod.mc_compat = "[1.20.5, 1.21.8]" +mod.mc_releases = ["1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8"] +deps.cloth_config = "14.0.139" +deps.neo_loader = "20.6.125" + +[neoforge."1.21.9"] +mod.version_name = "1.21.9-1.21.10" +mod.mc_compat = "[1.21.9, 1.21.10]" +mod.mc_releases = ["1.21.9", "1.21.10"] +deps.cloth_config = "20.0.149" +deps.neo_loader = "21.9.16-beta" + +[neoforge."1.21.11"] +mod.version_name = "1.21.11" +mod.mc_compat = "[1.21.11]" +mod.mc_releases = ["1.21.11"] +deps.cloth_config = "20.0.149" +deps.neo_loader = "21.11.38-beta" + +[neoforge."26.1"] +mod.version_name = "26.1" +mod.mc_compat = "[26.1, 26.1.2]" +mod.mc_releases = ["26.1", "26.1.1", "26.1.2"] +deps.cloth_config = "26.1.154" +deps.neo_loader = "26.1.2.83" + +[neoforge."26.2"] +mod.version_name = "26.2" +mod.mc_compat = "[26.2,)" +mod.mc_releases = ["26.2"] +deps.cloth_config = "26.2.155" +deps.neo_loader = "26.2.0.25-beta" diff --git a/versions/1.16.5-fabric/gradle.properties b/versions/1.16.5-fabric/gradle.properties deleted file mode 100644 index 30f726e..0000000 --- a/versions/1.16.5-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=1.16.x -mod.version_name=1.16.x -mod.mc_targets=1.16,1.16.1,1.16.2,1.16.3,1.16.4,1.16.5 - -deps.cloth_config_version=4.17.101 -deps.mod_menu_version=1.16.23 - -deps.java=8 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.16.5-forge/gradle.properties b/versions/1.16.5-forge/gradle.properties deleted file mode 100644 index b47e14a..0000000 --- a/versions/1.16.5-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.16, 1.16.5] -mod.version_name=1.16.x -mod.mc_targets=1.16,1.16.1,1.16.2,1.16.3,1.16.4,1.16.5 - -deps.forge_loader=36.2.34 - -deps.cloth_config_version=4.17.101 - -deps.java=8 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.17.1-fabric/gradle.properties b/versions/1.17.1-fabric/gradle.properties deleted file mode 100644 index b6e4c56..0000000 --- a/versions/1.17.1-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=>=1.17- <=1.18.2 -mod.version_name=1.17-1.18.2 -mod.mc_targets=1.17,1.17.1,1.18,1.18.1,1.18.2 - -deps.cloth_config_version=5.3.63 -deps.mod_menu_version=2.0.17 - -deps.java=8 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.17.1-forge/gradle.properties b/versions/1.17.1-forge/gradle.properties deleted file mode 100644 index 25f4d00..0000000 --- a/versions/1.17.1-forge/gradle.properties +++ /dev/null @@ -1,12 +0,0 @@ -mod.mc_dep=[1.17, 1.17.1] -mod.version_name=1.17.x -mod.mc_targets=1.17,1.17.1 - -deps.forge_loader=37.1.1 - -# 5.3.63 -deps.cloth_config_version=4.17.101 - -deps.java=8 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.18.2-forge/gradle.properties b/versions/1.18.2-forge/gradle.properties deleted file mode 100644 index 8d7ec5d..0000000 --- a/versions/1.18.2-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.18, 1.18.2] -mod.version_name=1.18.x -mod.mc_targets=1.18,1.18.1,1.18.2 - -deps.forge_loader=40.3.0 - -deps.cloth_config_version=6.5.102 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.19-fabric/gradle.properties b/versions/1.19-fabric/gradle.properties deleted file mode 100644 index b8f9b59..0000000 --- a/versions/1.19-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=>=1.19- <=1.19.2 -mod.version_name=1.19-1.19.2 -mod.mc_targets=1.19,1.19.1,1.19.2 - -deps.cloth_config_version=8.3.134 -deps.mod_menu_version=4.0.0 - -deps.java=17 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.19-forge/gradle.properties b/versions/1.19-forge/gradle.properties deleted file mode 100644 index b073a28..0000000 --- a/versions/1.19-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.19, 1.19.1, 1.19.2] -mod.version_name=1.19-1.19.2 -mod.mc_targets=1.19,1.19.1,1.19.2 - -deps.forge_loader=41.1.0 - -deps.cloth_config_version=8.3.134 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.19.4-fabric/gradle.properties b/versions/1.19.4-fabric/gradle.properties deleted file mode 100644 index b1431f1..0000000 --- a/versions/1.19.4-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=>=1.19.3- <=1.19.4 -mod.version_name=1.19.3-1.19.4 -mod.mc_targets=1.19.3,1.19.4 - -deps.cloth_config_version=9.0.94 -deps.mod_menu_version=5.1.0 - -deps.java=17 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.19.4-forge/gradle.properties b/versions/1.19.4-forge/gradle.properties deleted file mode 100644 index 5e5502a..0000000 --- a/versions/1.19.4-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.19.3, 1.19.4] -mod.version_name=1.19.3-1.19.4 -mod.mc_targets=1.19.3,1.19.4 - -deps.forge_loader=45.4.0 - -deps.cloth_config_version=8.3.134 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.20.1-fabric/gradle.properties b/versions/1.20.1-fabric/gradle.properties deleted file mode 100644 index 43b0c73..0000000 --- a/versions/1.20.1-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=>=1.20- <=1.21.8 -mod.version_name=1.20-1.21.8 -mod.mc_targets=1.20,1.20.1,1.20.2,1.20.3,1.20.4,1.20.5,1.20.6,1.21,1.21.1,1.21.2,1.21.3,1.21.4,1.21.5,1.21.6,1.21.7,1.21.8 - -deps.cloth_config_version=9.0.94 -deps.mod_menu_version=5.1.0 - -deps.java=17 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.20.1-forge/gradle.properties b/versions/1.20.1-forge/gradle.properties deleted file mode 100644 index b1e8b24..0000000 --- a/versions/1.20.1-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.20, 1.20.4] -mod.version_name=1.20-1.20.4 -mod.mc_targets=1.20,1.20.1,1.20.2,1.20.3,1.20.4 - -deps.forge_loader=47.3.0 - -deps.cloth_config_version=11.1.136 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.20.4-neoforge/gradle.properties b/versions/1.20.4-neoforge/gradle.properties deleted file mode 100644 index f1b6eb0..0000000 --- a/versions/1.20.4-neoforge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.20.2, 1.20.4] -mod.version_name=1.20.2-1.20.4 -mod.mc_targets=1.20.2,1.20.3,1.20.4 - -deps.neoforge_loader=20.4.237 - -deps.cloth_config_version=13.0.138 - -deps.java=17 - -loom.platform=neoforge \ No newline at end of file diff --git a/versions/1.20.6-forge/gradle.properties b/versions/1.20.6-forge/gradle.properties deleted file mode 100644 index 9691714..0000000 --- a/versions/1.20.6-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.20.5, 1.21.5] -mod.version_name=1.20.5-1.21.5 -mod.mc_targets=1.20.5,1.20.6,1.21,1.21.1,1.21.2,1.21.3,1.21.4,1.21.5 - -deps.forge_loader=50.2.0 - -deps.cloth_config_version=14.0.139 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.20.6-neoforge/gradle.properties b/versions/1.20.6-neoforge/gradle.properties deleted file mode 100644 index b17e6cc..0000000 --- a/versions/1.20.6-neoforge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.20.5, 1.21.8] -mod.version_name=1.20.5-1.21.8 -mod.mc_targets=1.20.5,1.20.6,1.21,1.21.1,1.21.2,1.21.3,1.21.4,1.21.5,1.21.6,1.21.7,1.21.8 - -deps.neoforge_loader=20.6.125 - -deps.cloth_config_version=14.0.139 - -deps.java=21 - -loom.platform=neoforge diff --git a/versions/1.21.11-fabric/gradle.properties b/versions/1.21.11-fabric/gradle.properties deleted file mode 100644 index e011017..0000000 --- a/versions/1.21.11-fabric/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=>=1.21.11- <26.1 -# https://www.minecraft.net/en-us/article/minecraft-new-version-numbering-system -mod.version_name=1.21.11 -mod.mc_targets=1.21.11 - -deps.cloth_config_version=17.0.144 -deps.mod_menu_version=16.0.0 - -deps.java=17 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.21.11-forge/gradle.properties b/versions/1.21.11-forge/gradle.properties deleted file mode 100644 index 3cc2b91..0000000 --- a/versions/1.21.11-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.21.11,) -mod.version_name=1.21.11 -mod.mc_targets=1.21.11 - -deps.forge_loader=61.1.0 - -deps.cloth_config_version=17.0.144 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.21.11-neoforge/gradle.properties b/versions/1.21.11-neoforge/gradle.properties deleted file mode 100644 index 1271ca4..0000000 --- a/versions/1.21.11-neoforge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.21.11,) -mod.version_name=1.21.11 -mod.mc_targets=1.21.11 - -deps.neoforge_loader=21.11.38-beta - -deps.cloth_config_version=20.0.149 - -deps.java=21 - -loom.platform=neoforge diff --git a/versions/1.21.6-forge/gradle.properties b/versions/1.21.6-forge/gradle.properties deleted file mode 100644 index 1140417..0000000 --- a/versions/1.21.6-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.21.6, 1.21.8] -mod.version_name=1.21.6-1.21.8 -mod.mc_targets=1.21.6,1.21.7,1.21.8 - -deps.forge_loader=56.0.2 - -deps.cloth_config_version=17.0.144 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.21.9-fabric/gradle.properties b/versions/1.21.9-fabric/gradle.properties deleted file mode 100644 index 3de815c..0000000 --- a/versions/1.21.9-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=>=1.21.9- <=1.21.10 -mod.version_name=1.21.9-1.21.10 -mod.mc_targets=1.21.9,1.21.10 - -deps.cloth_config_version=17.0.144 -deps.mod_menu_version=16.0.0 - -deps.java=17 - -loom.platform=fabric \ No newline at end of file diff --git a/versions/1.21.9-forge/gradle.properties b/versions/1.21.9-forge/gradle.properties deleted file mode 100644 index 3aee65b..0000000 --- a/versions/1.21.9-forge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.21.9, 1.21.10] -mod.version_name=1.21.9-1.21.10 -mod.mc_targets=1.21.9,1.21.10 - -deps.forge_loader=59.0.5 - -deps.cloth_config_version=17.0.144 - -deps.java=17 - -loom.platform=forge \ No newline at end of file diff --git a/versions/1.21.9-neoforge/gradle.properties b/versions/1.21.9-neoforge/gradle.properties deleted file mode 100644 index f6c3360..0000000 --- a/versions/1.21.9-neoforge/gradle.properties +++ /dev/null @@ -1,11 +0,0 @@ -mod.mc_dep=[1.21.9, 1.21.10] -mod.version_name=1.21.9-1.21.10 -mod.mc_targets=1.21.9,1.21.10 - -deps.neoforge_loader=21.9.16-beta - -deps.cloth_config_version=20.0.149 - -deps.java=21 - -loom.platform=neoforge diff --git a/versions/26.1-fabric/gradle.properties b/versions/26.1-fabric/gradle.properties deleted file mode 100644 index 42e15e6..0000000 --- a/versions/26.1-fabric/gradle.properties +++ /dev/null @@ -1,10 +0,0 @@ -mod.mc_dep=>=26.1 -mod.version_name=26.1 -mod.mc_targets=26.1 - -deps.cloth_config_version=26.1.154 -deps.mod_menu_version=18.0.0-alpha.8 - -deps.java=25 - -loom.platform=fabric \ No newline at end of file From ddb63e67da439b80d4811f8bf274a87a69cf8aed Mon Sep 17 00:00:00 2001 From: NotCoded Date: Sun, 19 Jul 2026 01:07:17 +0200 Subject: [PATCH 2/2] fix(forge): make 26.1 and 26.2 targets build - drop corrupted IDE auto-imports and Entities.EscapeMode reference that broke buildscript compilation for every forge target - guard mappings/remapJar behind obfuscated flag; 26.x uses loom-no-remap where remap tasks do not exist (matches fabric script) - shedaniel ships no Forge cloth-config past 17.0.144 (MC 1.21.3); 26.x pulls the community port maven.modrinth:cloth-config-forge (same cloth_config modid) via Modrinth maven - add missing [forge."26.2"] properties (Forge 65.0.5, cloth 26.2.155) - ModList.get() removed in Forge 62+; API is static, add >=26.1 guard --- build.forge.gradle.kts | 21 ++++++++++++------- .../xyzcopy/platforms/forge/XYZCopyForge.java | 5 ++++- stonecutter.properties.toml | 7 +++++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/build.forge.gradle.kts b/build.forge.gradle.kts index 860dff2..97dbf22 100644 --- a/build.forge.gradle.kts +++ b/build.forge.gradle.kts @@ -1,9 +1,6 @@ -import com.sun.imageio.plugins.jpeg.JPEG.vendor import dev.kikugie.stonecutter.data.deserialization.SCList import dev.kikugie.stonecutter.data.deserialization.SCPrimitive -import jdk.jfr.internal.JVM.exclude import me.modmuss50.mpp.ReleaseType -import org.gradle.internal.impldep.org.jsoup.nodes.Entities plugins { id("loom-plugin-chooser") @@ -14,11 +11,12 @@ val modVersion = property("mod.version") as String val modId = property("mod.id") as String val mcCompat = property("mod.mc_compat") as String val versionName = property("mod.version_name") as String +val obfuscated = sc.current.version.startsWith("1.") val clothSep = if (sc.current.version == "1.16.5") "-" else "_" version = "$modVersion+$versionName-forge" group = property("mod.group") as String -Entities.EscapeMode.base.archivesName = modId +base.archivesName = modId val requiredJava: JavaVersion = when { sc.current.parsed >= "26.1" -> JavaVersion.VERSION_25 @@ -31,13 +29,20 @@ val requiredJava: JavaVersion = when { repositories { maven("https://maven.shedaniel.me/") maven("https://maven.minecraftforge.net/") + exclusiveContent { + forRepository { maven("https://api.modrinth.com/maven") } + filter { includeGroup("maven.modrinth") } + } } dependencies { minecraft("com.mojang:minecraft:${sc.current.version}") - mappings(loom.officialMojangMappings()) + if (obfuscated) mappings(loom.officialMojangMappings()) "forge"("net.minecraftforge:forge:${sc.current.version}-${property("deps.forge_loader")}") - modImplementation("me.shedaniel.cloth:cloth-config-forge:${property("deps.cloth_config")}") + // shedaniel stopped shipping Forge builds after 1.21.x; 26.x+ uses the + // community port (https://modrinth.com/mod/cloth-config-forge) + val clothGroup = if (obfuscated) "me.shedaniel.cloth" else "maven.modrinth" + modImplementation("$clothGroup:cloth-config-forge:${property("deps.cloth_config")}") } loom { @@ -81,7 +86,7 @@ tasks { } register("buildAndCollect") { group = "build" - from(named("remapJar"), named("remapSourcesJar")) + from(named(if (obfuscated) "remapJar" else "jar"), named(if (obfuscated) "remapSourcesJar" else "sourcesJar")) into(rootProject.layout.buildDirectory.file("libs/$modVersion/forge")) } } @@ -95,7 +100,7 @@ val mcReleases = (sc.properties.raw("mod", "mc_releases") as SCList) .map { (it as SCPrimitive).content.toString() } publishMods { - file = tasks.named("remapJar").flatMap { it.archiveFile } + file = tasks.named(if (obfuscated) "remapJar" else "jar").flatMap { it.archiveFile } type = ReleaseType.STABLE displayName = "Forge | $versionName [v$modVersion]" version = project.version.toString() diff --git a/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java b/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java index bf38b57..200bc3f 100644 --- a/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java +++ b/src/main/java/net/notcoded/xyzcopy/platforms/forge/XYZCopyForge.java @@ -123,7 +123,10 @@ public String getModLoader() { @Override public boolean isModLoaded(String modId) { - return ModList.get().isLoaded(modId); + //? if >=26.1 { + return ModList.isLoaded(modId); + //?} else { + /^return ModList.get().isLoaded(modId);^///?} } @Override diff --git a/stonecutter.properties.toml b/stonecutter.properties.toml index 9818377..1bc4158 100644 --- a/stonecutter.properties.toml +++ b/stonecutter.properties.toml @@ -154,6 +154,13 @@ mod.mc_releases = ["26.1", "26.1.1", "26.1.2"] deps.cloth_config = "26.1.154" deps.forge_loader = "62.0.9" +[forge."26.2"] +mod.version_name = "26.2" +mod.mc_compat = "[26.2,)" +mod.mc_releases = ["26.2"] +deps.cloth_config = "26.2.155" +deps.forge_loader = "65.0.5" + [neoforge."1.20.4"] mod.version_name = "1.20.2-1.20.4" mod.mc_compat = "[1.20.2, 1.20.4]"