diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c2a3f3..479cd29 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,30 +1,49 @@ -# 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. +# Build the mod against every Minecraft variant Stonecutter is configured for. +# Each matrix job builds one variant (1.21, 1.21.6, 26.1) and uploads its jar. +# Running `./gradlew build` from the root would also work but the matrix gives +# clearer failure attribution and parallel execution. name: build on: [pull_request, push] jobs: build: + name: build mc${{ matrix.mc }} runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + include: + - mc: '1.21' + java: '21' + - mc: '1.21.6' + java: '21' + - mc: '26.1' + java: '25' steps: - name: checkout repository uses: actions/checkout@v6 + - name: validate gradle wrapper uses: gradle/actions/wrapper-validation@v6 - - name: setup jdk + + - name: setup jdk ${{ matrix.java }} uses: actions/setup-java@v5 with: - java-version: '25' + java-version: ${{ matrix.java }} distribution: 'microsoft' + + # Stonecutter's `build.gradle` uses Java toolchains, so loom can compile + # against an older JDK even when Gradle itself runs on a newer one. We + # still set the matrix Java as the daemon JVM for simplicity. - name: make gradle wrapper executable run: chmod +x ./gradlew - - name: build - run: ./gradlew build - - name: capture build artifacts + + - name: build :${{ matrix.mc }}:build + run: ./gradlew :${{ matrix.mc }}:build --stacktrace + + - name: upload jar uses: actions/upload-artifact@v7 with: - name: Artifacts - path: build/libs/ \ No newline at end of file + name: betterhud-mc${{ matrix.mc }} + path: versions/${{ matrix.mc }}/build/libs/*.jar diff --git a/.gitignore b/.gitignore index c476faf..8c52ed7 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,14 @@ bin/ run/ +# stonecutter + +versions/*/.gradle/ +versions/*/build/ +versions/*/run/ +versions/*/src/ +*.stonecutter.tmp + # java hs_err_*.log diff --git a/build.gradle b/build.gradle index 41f2871..3b8a1b5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,87 +1,131 @@ plugins { - id 'net.fabricmc.fabric-loom' version "${loom_version}" + // Loom 1.14+ splits into two sibling plugins: + // - `net.fabricmc.fabric-loom-remap` handles obfuscated MC (1.21.x with intermediary) + // - `net.fabricmc.fabric-loom` handles unobfuscated MC (26.1+, Mojang names native) + // We declare both with `apply false` and pick the right one for the current variant. + id 'net.fabricmc.fabric-loom-remap' version "${loom_version}" apply false + id 'net.fabricmc.fabric-loom' version "${loom_version}" apply false id 'maven-publish' } -version = project.mod_version +def mcVersion = stonecutter.current.version +def isLegacy = stonecutter.eval(mcVersion, '<26') // 1.21.x family +def hasHudElementRegistry = stonecutter.eval(mcVersion, '>=1.21.6') // 1.21.6+ and 26+ + +apply plugin: isLegacy ? 'net.fabricmc.fabric-loom-remap' : 'net.fabricmc.fabric-loom' + +// `stonecutter` is injected into each version subproject. `stonecutter.current.version` +// is the MC string, e.g. "1.21", "1.21.6", "26.1". +// Per-MC Java version (21 for 1.21.x, 25 for 26.1+). +def javaVersionInt = Integer.parseInt(project.java_version) +def javaLang = JavaVersion.toVersion(javaVersionInt) +def mixinJavaCompat = "JAVA_${javaVersionInt}" + +version = "${project.mod_version}+mc${mcVersion}" group = project.maven_group +base { + archivesName = project.archives_base_name +} + repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. - - maven { url "https://maven.shedaniel.me/" } - maven { url "https://maven.terraformersmc.com/releases/" } + maven { url 'https://maven.shedaniel.me/' } + maven { url 'https://maven.terraformersmc.com/releases/' } } -configurations.configureEach { - if (name.toLowerCase().contains('annotationprocessor')) { - exclude group: 'org.ow2.asm' +// MC 26+ uses fabric-rendering-v1's transitive deps but rejects ASM coming from +// annotation processors; matches main's existing build. +if (!isLegacy) { + configurations.configureEach { + if (name.toLowerCase().contains('annotationprocessor')) { + exclude group: 'org.ow2.asm' + } } } +// MC 26+ ships with Mojang official names baked into the runtime, so loom skips +// the intermediary remap entirely - mods link directly via `implementation` +// and `mappings` must NOT be declared. +// 1.21.x uses intermediary at runtime, so deps must go through `modImplementation` +// for loom to remap them, and `mappings loom.officialMojangMappings()` is required. dependencies { - // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - - implementation "net.fabricmc:fabric-loader:${project.loader_version}" - - // Fabric API. This is technically optional, but you probably want it anyway. - implementation include(fabricApi.module("fabric-api-base", project.fabric_api_version)) - implementation include(fabricApi.module("fabric-rendering-v1", project.fabric_api_version)) - - implementation include("com.terraformersmc:modmenu:${project.modmenu_version}") - implementation include("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { - exclude(group: "net.fabricmc.fabric-api") - } + + if (isLegacy) { + mappings loom.officialMojangMappings() + + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation include(fabricApi.module('fabric-api-base', project.fabric_api_version)) + modImplementation include(fabricApi.module('fabric-rendering-v1', project.fabric_api_version)) + + // 1.21 (pre-1.21.6) needs lifecycle-events as an explicit module; later versions + // pull it transitively through rendering-v1. + if (!hasHudElementRegistry) { + modImplementation include(fabricApi.module('fabric-lifecycle-events-v1', project.fabric_api_version)) + } + + modImplementation include("com.terraformersmc:modmenu:${project.modmenu_version}") + modImplementation include("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { + exclude(group: 'net.fabricmc.fabric-api') + } + } else { + implementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation include(fabricApi.module('fabric-api-base', project.fabric_api_version)) + implementation include(fabricApi.module('fabric-rendering-v1', project.fabric_api_version)) + + implementation include("com.terraformersmc:modmenu:${project.modmenu_version}") + implementation include("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { + exclude(group: 'net.fabricmc.fabric-api') + } + } } processResources { - inputs.property "version", project.version + def expansion = [ + version : project.version, + minecraftReq : project.mc_dep, + loaderReq : project.loader_dep, + javaReq : ">=${javaVersionInt}", + javaCompat : mixinJavaCompat + ] + inputs.properties expansion - filesMatching("fabric.mod.json") { - expand "version": inputs.properties.version + filesMatching('fabric.mod.json') { + expand expansion + } + filesMatching('betterhud.mixins.json') { + expand expansion } } tasks.withType(JavaCompile).configureEach { - it.options.release = 25 + it.options.release = javaVersionInt } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_25 - targetCompatibility = JavaVersion.VERSION_25 + sourceCompatibility = javaLang + targetCompatibility = javaLang + toolchain { + languageVersion = JavaLanguageVersion.of(javaVersionInt) + } } jar { - inputs.property "projectName", project.name - - from("LICENSE") { - rename { "${it}_${project.name}"} + def archiveName = base.archivesName.get() + from('../../LICENSE') { + rename { "${it}_${archiveName}" } } } -// configure the maven publication publishing { publications { - create("mavenJava", MavenPublication) { + create('mavenJava', MavenPublication) { + artifactId = "${project.archives_base_name}-mc${mcVersion}" from components.java } } - - // 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. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. + // Add publish repos here if/when needed. } -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index a7faad0..07e740a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,22 +1,18 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G +org.gradle.jvmargs=-Xmx2G org.gradle.parallel=true # IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349 org.gradle.configuration-cache=false -# Fabric Properties -# check these on https://fabricmc.net/develop -minecraft_version=26.1 -loader_version=0.19.2 +# Acknowledge using Groovy DSL with Stonecutter (Kotlin DSL is recommended but Groovy works). +dev.kikugie.stonecutter.hard_mode=true + +# Single loom version covers all MC variants. The `fabric-loom-remap` plugin id +# handles obfuscated MC (1.21.x), while `fabric-loom` handles unobfuscated MC (26.1+). loom_version=1.16-SNAPSHOT -# Mod Properties +# Mod Properties (shared) mod_version=2.1.0 maven_group=dsns.betterhud archives_base_name=betterhud - -# Dependencies -fabric_api_version=0.145.1+26.1 -modmenu_version=18.0.0-alpha.8 -cloth_config_version=26.1.154 \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/settings.gradle b/settings.gradle index bcb1c6e..c38a828 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,10 +4,34 @@ pluginManagement { name = 'Fabric' url = 'https://maven.fabricmc.net/' } + maven { + name = 'Stonecutter Releases' + url = 'https://maven.kikugie.dev/releases' + } + maven { + name = 'Stonecutter Snapshots' + url = 'https://maven.kikugie.dev/snapshots' + } mavenCentral() gradlePluginPortal() } } -// Should match your modid +plugins { + id 'dev.kikugie.stonecutter' version '0.9.3' +} + +stonecutter { + create(rootProject) { + // Each entry is one buildable variant. The string is both the subproject name + // and the MC version. These cover support/1.21-1.21.5, support/1.21.6-1.21.11, + // and main 26.1. + versions('1.21', '1.21.6', '26.1') + + // vcsVersion is the variant whose form is used as the canonical (active) version + // in source. We pick 26.1 so `git diff main` stays small. + vcsVersion = '26.1' + } +} + rootProject.name = 'betterhud' diff --git a/src/main/java/dsns/betterhud/BetterHUD.java b/src/main/java/dsns/betterhud/BetterHUD.java index bbf7edb..39bd452 100644 --- a/src/main/java/dsns/betterhud/BetterHUD.java +++ b/src/main/java/dsns/betterhud/BetterHUD.java @@ -8,8 +8,16 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +//? if >=1.21.6 { import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry; +//?} else { +/*import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; +*///?} +//? if >=26 { import net.minecraft.resources.Identifier; +//?} else if >=1.21.6 { +/*import net.minecraft.resources.ResourceLocation;*/ +//?} import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,10 +47,19 @@ public void onInitializeClient() { BetterHUDGUI betterHUDGUI = new BetterHUDGUI(); + //? if >=26 { HudElementRegistry.addLast( Identifier.fromNamespaceAndPath("betterhud", "hud"), betterHUDGUI::onHudRender ); + //?} else if >=1.21.6 { + /*HudElementRegistry.addLast( + ResourceLocation.fromNamespaceAndPath("betterhud", "hud"), + betterHUDGUI::onHudRender + );*/ + //?} else { + /*HudRenderCallback.EVENT.register(betterHUDGUI); + *///?} ClientTickEvents.START_CLIENT_TICK.register(betterHUDGUI); } } diff --git a/src/main/java/dsns/betterhud/BetterHUDGUI.java b/src/main/java/dsns/betterhud/BetterHUDGUI.java index 7d2b187..aea1e82 100644 --- a/src/main/java/dsns/betterhud/BetterHUDGUI.java +++ b/src/main/java/dsns/betterhud/BetterHUDGUI.java @@ -6,11 +6,22 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +//? if <1.21.6 { +/*import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; +*///?} import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; +//? if >=26 { import net.minecraft.client.gui.GuiGraphicsExtractor; +//?} else { +/*import net.minecraft.client.gui.GuiGraphics; +*///?} +//? if >=1.21.6 { public class BetterHUDGUI implements ClientTickEvents.StartTick { +//?} else { +/*public class BetterHUDGUI implements HudRenderCallback, ClientTickEvents.StartTick { +*///?} public static int verticalPadding = 4; public static int horizontalPadding = 4; @@ -68,7 +79,11 @@ public void onStartTick(Minecraft client) { } public void onHudRender( + //? if >=26 { GuiGraphicsExtractor drawContext, + //?} else { + /*GuiGraphics drawContext, + *///?} DeltaTracker tickCounter ) { if (client.getDebugOverlay().showDebugScreen()) return; @@ -145,7 +160,11 @@ public void onHudRender( } private void drawString( + //? if >=26 { GuiGraphicsExtractor drawContext, + //?} else { + /*GuiGraphics drawContext, + *///?} CustomText text, int x, int y @@ -160,6 +179,7 @@ private void drawString( text.backgroundColor ); + //? if >=26 { drawContext.text( client.font, text.text, @@ -168,5 +188,15 @@ private void drawString( text.color, true ); + //?} else { + /*drawContext.drawString( + client.font, + text.text, + x + horizontalPadding, + y + verticalPadding, + text.color, + true + ); + *///?} } } diff --git a/src/main/java/dsns/betterhud/mods/Biome.java b/src/main/java/dsns/betterhud/mods/Biome.java index 73289be..e455125 100644 --- a/src/main/java/dsns/betterhud/mods/Biome.java +++ b/src/main/java/dsns/betterhud/mods/Biome.java @@ -5,8 +5,15 @@ import dsns.betterhud.util.ModSettings; import java.util.LinkedHashMap; import java.util.Map; +//? if <26 { +/*import java.util.Optional; +*///?} import net.minecraft.client.Minecraft; +//? if >=26 { import net.minecraft.core.Holder; +//?} else { +/*import net.minecraft.resources.ResourceKey; +*///?} import net.minecraft.world.entity.player.Player; public class Biome implements BaseMod { @@ -30,11 +37,20 @@ public CustomText onStartTick(Minecraft client) { if (player == null) return null; // have to specify this because name of class is Biome + //? if >=26 { Holder biome = client.level.getBiome(player.blockPosition()); if (!biome.unwrapKey().isPresent()) return null; String biomeString = formatSnakeCase(biome.getRegisteredName().replace("minecraft:", "")); + //?} else { + /*Optional> biome = + client.level.getBiome(player.blockPosition()).unwrapKey(); + + if (!biome.isPresent()) return null; + + String biomeString = formatSnakeCase(biome.get().location().getPath()); + *///?} // used to maintain order when iterating LinkedHashMap biomeColors = new LinkedHashMap<>(); diff --git a/src/main/resources/betterhud.mixins.json b/src/main/resources/betterhud.mixins.json index 370eecf..c35b39c 100644 --- a/src/main/resources/betterhud.mixins.json +++ b/src/main/resources/betterhud.mixins.json @@ -1,7 +1,7 @@ { "required": true, "package": "dsns.betterhud.mixin", - "compatibilityLevel": "JAVA_25", + "compatibilityLevel": "${javaCompat}", "client": [], "injectors": { "defaultRequire": 1 @@ -9,4 +9,4 @@ "overwrites": { "requireAnnotations": true } -} \ No newline at end of file +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 31b270b..b116dc0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -21,8 +21,8 @@ "betterhud.mixins.json" ], "depends": { - "fabricloader": ">=0.19", - "minecraft": ">=26", - "java": ">=25" + "fabricloader": "${loaderReq}", + "minecraft": "${minecraftReq}", + "java": "${javaReq}" } -} \ No newline at end of file +} diff --git a/stonecutter.gradle b/stonecutter.gradle new file mode 100644 index 0000000..55aa818 --- /dev/null +++ b/stonecutter.gradle @@ -0,0 +1,11 @@ +plugins { + id 'dev.kikugie.stonecutter' +} + +// The "active" version determines which variant the source tree currently shows +// uncommented. Switch with `./gradlew "Set active version to "` (Stonecutter task). +stonecutter.active('26.1') /* [SC] DO NOT EDIT */ + +// Stonecutter 0.7+ no longer needs explicit `registerChiseled` task: running +// `./gradlew build` from the root automatically runs `build` for every version +// subproject. Per-version commands like `./gradlew :1.21:build` also work. diff --git a/versions/1.21.6/gradle.properties b/versions/1.21.6/gradle.properties new file mode 100644 index 0000000..1c59190 --- /dev/null +++ b/versions/1.21.6/gradle.properties @@ -0,0 +1,14 @@ +# Builds against MC 1.21.9 (a stable point in the 1.21.6-1.21.11 range). +# fabric.mod.json declares >=1.21.6 <1.22 so it loads on 1.21.6-1.21.11. +minecraft_version=1.21.9 +loader_version=0.17.3 +java_version=21 + +# fabric.mod.json range +mc_dep=>=1.21.6 <1.22 +loader_dep=>=0.16.10 + +# Fabric API + ecosystem (matches support/1.21.6-1.21.11 branch). +fabric_api_version=0.134.0+1.21.9 +modmenu_version=15.0.2 +cloth_config_version=19.0.147 diff --git a/versions/1.21/gradle.properties b/versions/1.21/gradle.properties new file mode 100644 index 0000000..4d2e6ac --- /dev/null +++ b/versions/1.21/gradle.properties @@ -0,0 +1,14 @@ +# Builds against MC 1.21 itself (lowest in the 1.21-1.21.5 range, for max +# backward compat). fabric.mod.json declares ~1.21 so it loads on 1.21-1.21.5. +minecraft_version=1.21 +loader_version=0.17.3 +java_version=21 + +# fabric.mod.json range +mc_dep=~1.21 +loader_dep=>=0.15.11 + +# Fabric API + ecosystem (matches support/1.21-1.21.5 branch). +fabric_api_version=0.102.0+1.21 +modmenu_version=14.0.2 +cloth_config_version=19.0.147 diff --git a/versions/26.1/gradle.properties b/versions/26.1/gradle.properties new file mode 100644 index 0000000..c5050b1 --- /dev/null +++ b/versions/26.1/gradle.properties @@ -0,0 +1,12 @@ +minecraft_version=26.1 +loader_version=0.19.2 +java_version=25 + +# fabric.mod.json range +mc_dep=>=26 +loader_dep=>=0.19 + +# Fabric API + ecosystem +fabric_api_version=0.145.1+26.1 +modmenu_version=18.0.0-alpha.8 +cloth_config_version=26.1.154