From 147b494c26b52f195f06fb52b78cf99ee26051a6 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Fri, 11 Sep 2026 12:20:37 +0100 Subject: [PATCH 1/2] Port Mineralogy 6.1.2 to Minecraft 26.2 NeoForge --- .github/workflows/ci.yml | 33 ++++---- .github/workflows/codeql-analysis.yml | 4 +- .github/workflows/validate-gradle-build.yml | 4 +- CHANGELOG.txt | 24 ++++++ README.md | 10 +-- build.gradle | 81 +++++++++++++------ docs/CONTENT_CONFIG.md | 2 +- docs/DEVELOPER_GUIDE.md | 26 +++--- docs/PLAYER_GUIDE.md | 18 ++--- docs/PROVIDER.md | 8 +- docs/README.md | 2 +- docs/VERSIONS.md | 19 ++--- gradle.properties | 20 +++-- resourcepack/x128/pack.mcmeta | 4 +- resourcepack/x16/pack.mcmeta | 4 +- resourcepack/x32/pack.mcmeta | 4 +- resourcepack/x64/pack.mcmeta | 4 +- scripts/generate-locales.ps1 | 2 +- scripts/generate-recipes.ps1 | 32 ++++---- .../compat/CobblestoneTagPolicy.java | 4 +- .../init/RegistrationProperties.java | 2 +- .../mineralogy/items/MineralFertilizer.java | 2 +- .../OreSpawnEarlyTagCompatibilityMixin.java | 2 +- .../mixin/ReloadableServerResourcesMixin.java | 2 +- .../resources/META-INF/accesstransformer.cfg | 2 +- .../data/minecraft/recipe/brewing_stand.json | 1 - .../coast_armor_trim_smithing_template.json | 1 - .../data/minecraft/recipe/furnace.json | 1 - .../sentry_armor_trim_smithing_template.json | 1 - .../vex_armor_trim_smithing_template.json | 1 - src/main/resources/pack.mcmeta | 4 +- .../resources/META-INF/neoforge.mods.toml | 4 +- .../resources/pack.mcmeta | 4 +- .../resources/META-INF/neoforge.mods.toml | 4 +- .../resources/pack.mcmeta | 4 +- .../mineralogy/LocalizationQualityTest.java | 2 +- .../mc/mineralogy/ResourceContractTest.java | 65 ++++++++++++--- .../mc/mineralogy/WorkflowContractTest.java | 23 ++++-- 38 files changed, 269 insertions(+), 161 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b082f4c4..6093e5a9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,19 +1,19 @@ -name: Mineralogy 26.1.2 NeoForge CI +name: Mineralogy 26.2 NeoForge CI on: push: branches: - - master-26.1.2-neo + - master-26.2-neo - 'feature/**' pull_request: branches: - - master-26.1.2-neo + - master-26.2-neo permissions: contents: read concurrency: - group: mineralogy-26.1.2-neo-${{ github.workflow }}-${{ github.ref }} + group: mineralogy-26.2-neo-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -72,12 +72,17 @@ jobs: run: | set -euo pipefail chmod +x ./gradlew - ./gradlew clean check build javadoc verifyReleaseConfiguration verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums \ - -PorespawnVerificationRepository="${{ steps.orespawn.outputs.repository }}" \ - --no-daemon --stacktrace --max-workers=2 \ - "-Dorg.gradle.java.installations.paths=$JAVA_HOME" \ - -Dorg.gradle.java.installations.auto-detect=false \ + gradle_jdk_args=( + "-Dorg.gradle.java.installations.paths=$JAVA_HOME" + -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.java.installations.auto-download=false + ) + ./gradlew clean \ + -PorespawnVerificationRepository="${{ steps.orespawn.outputs.repository }}" \ + --no-daemon --stacktrace --max-workers=2 "${gradle_jdk_args[@]}" + ./gradlew check build javadoc verifyReleaseConfiguration verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums \ + -PorespawnVerificationRepository="${{ steps.orespawn.outputs.repository }}" \ + --no-daemon --stacktrace --max-workers=2 "${gradle_jdk_args[@]}" - name: Generate and audit Eclipse production launches shell: bash run: | @@ -91,20 +96,20 @@ jobs: - name: Upload audited release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: Mineralogy-26.1.2-neoforge-${{ github.sha }} + name: Mineralogy-26.2-neoforge-${{ github.sha }} if-no-files-found: error retention-days: 30 path: | - build/libs/Mineralogy-6.1.2.2601022.jar - build/libs/Mineralogy-6.1.2.2601022-sources.jar - build/libs/Mineralogy-6.1.2.2601022-javadoc.jar + build/libs/Mineralogy-6.1.2.2602002.jar + build/libs/Mineralogy-6.1.2.2602002-sources.jar + build/libs/Mineralogy-6.1.2.2602002-javadoc.jar build/release/SHA256SUMS CHANGELOG.txt - name: Upload diagnostics on failure if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: Mineralogy-26.1.2-neoforge-diagnostics-${{ github.sha }} + name: Mineralogy-26.2-neoforge-diagnostics-${{ github.sha }} if-no-files-found: ignore retention-days: 14 path: | diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e331c11a9..1109fd92f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -3,11 +3,11 @@ name: CodeQL on: push: branches: - - master-26.1.2-neo + - master-26.2-neo - 'feature/**' pull_request: branches: - - master-26.1.2-neo + - master-26.2-neo schedule: - cron: '43 7 * * 4' diff --git a/.github/workflows/validate-gradle-build.yml b/.github/workflows/validate-gradle-build.yml index 4e4880adb..28b307405 100644 --- a/.github/workflows/validate-gradle-build.yml +++ b/.github/workflows/validate-gradle-build.yml @@ -3,11 +3,11 @@ name: Validate Gradle Wrapper on: push: branches: - - master-26.1.2-neo + - master-26.2-neo - 'feature/**' pull_request: branches: - - master-26.1.2-neo + - master-26.2-neo permissions: contents: read diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 01da69c8d..6bc3d38fd 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,27 @@ +Mineralogy 6.1.2.2602002 for Minecraft 26.2 NeoForge + +- Ported the accepted NeoForge 26.1.2 product to Minecraft 26.2 and + NeoForge 26.2.0.45-beta while preserving every registry, block-entity, NBT, + provider, configuration, migration, recipe, locale, guide, crude-oil, + relief, mining, furnace, creative-tab, texture, and legacy-world identity. +- Retained the established NeoForge registration, capabilities, fluid models, + tag reload policy, and Java-25 Mixin conversion path. The complete 18,192 + legacy mappings, dual Overworld region layouts, selected-world restoration, + sidecars, chunk protection, and furnace normalization remain intact. +- Regenerated the five changed vanilla overrides without Minecraft 26.2's + removed crafting category field. The remaining 1,433 Mineralogy recipes, + progressive advancements, tuff matrix, slab precedence, stone-spear support, + and all 19 configurable cobblestone routes are unchanged. +- Kept Minecraft's new sulfur and cinnabar families separate from Mineralogy's + sulfur ore, dust, storage block, recipes, tags, and OreSpawn provider rule. +- Removed the 26.1.2-only NeoGradle source-decompiler workaround and adopted + the validated 26.2 binary userdev path, while retaining the MMD Maven primary + and checksum-verified CurseMaven fallback for OreSpawn. +- Updated metadata, packs, CI, documentation, and release audits for Minecraft + 26.2, NeoForge 26.2.0.45-beta, OreSpawn 4.0.16.2602002, Java 25, + resource format 88, and data format 107.1. Mineralogy still registers no + world generator. + Mineralogy 6.1.2.2601022 for Minecraft 26.1.2 NeoForge - Ported the accepted NeoForge 1.21.11 product to Minecraft 26.1.2 and diff --git a/README.md b/README.md index bbb54f31f..847ae1e0a 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ [![Discord](https://img.shields.io/badge/Discord-MMD-green.svg?style=flat&logo=Discord)](https://discord.moddev.zone) [![CurseForge downloads](https://cf.way2muchnoise.eu/full_minecraft-mineralogy_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/minecraft-mineralogy) [![Supported Minecraft versions](https://cf.way2muchnoise.eu/versions/Minecraft_minecraft-mineralogy_all.svg)](https://www.curseforge.com/minecraft/mc-mods/minecraft-mineralogy) -[![Build, test, and audit](https://github.com/MinecraftModDevelopmentMods/MinecraftMineralogy/actions/workflows/ci.yml/badge.svg?branch=master-26.1.2-neo)](https://github.com/MinecraftModDevelopmentMods/MinecraftMineralogy/actions/workflows/ci.yml?query=branch%3Amaster-26.1.2-neo) +[![Build, test, and audit](https://github.com/MinecraftModDevelopmentMods/MinecraftMineralogy/actions/workflows/ci.yml/badge.svg?branch=master-26.2-neo)](https://github.com/MinecraftModDevelopmentMods/MinecraftMineralogy/actions/workflows/ci.yml?query=branch%3Amaster-26.2-neo) -# Mineralogy 6 for Minecraft 26.1.2 +# Mineralogy 6 for Minecraft 26.2 Mineralogy adds real-world rock families, matching construction blocks, mineral ores and dusts, rock furnaces, drywall, rock-salt lighting, fertilizer, and crude oil. OreSpawn 4 is the sole terrain, strata, ore, and deposit engine; Mineralogy no longer installs a parallel world generator. -This branch builds Mineralogy `6.1.2.2601022` for NeoForge `26.1.2.94` and is built -and tested against OreSpawn `4.0.16.2601022`. Its declared compatibility range is +This branch builds Mineralogy `6.1.2.2602002` for NeoForge `26.2.0.45-beta` and is built +and tested against OreSpawn `4.0.16.2602002`. Its declared compatibility range is OreSpawn `[4.0.6,5.0.0)`. Install both mods on clients and servers. This is the NeoForge build. It is intentionally maintained separately from the -Forge 26.1.2 branch; use the jar that matches the loader in your modpack. +Forge 26.2 branch; use the jar that matches the loader in your modpack. ## Configuration and help diff --git a/build.gradle b/build.gradle index 3c906612d..b6ddf52fe 100644 --- a/build.gradle +++ b/build.gradle @@ -44,8 +44,8 @@ def versionParts = project.mod_version.toString().tokenize('.') if (versionParts.size() != 4 || !versionParts.every { it ==~ /\d+/ }) { throw new GradleException("mod_version must use Major.Minor.Bug.Target numeric form: ${project.mod_version}") } -if (versionParts[3] != '2601022') { - throw new GradleException("Mineralogy 26.1.2 NeoForge releases must use target 2601022: ${project.mod_version}") +if (versionParts[3] != '2602002') { + throw new GradleException("Mineralogy 26.2 NeoForge releases must use target 2602002: ${project.mod_version}") } java { @@ -77,6 +77,17 @@ tasks.named('compileTestJava', JavaCompile) { options.compilerArgs.add('-proc:none') } +// NeoGradle stores downloaded vanilla executables in its project-local cache. +// Preserve complete cached executables during an offline rerun; missing or +// incomplete entries still execute normally and retain NeoGradle's diagnostic. +tasks.matching { task -> task.name.startsWith('cacheVersionExecutable') }.configureEach { + onlyIf { + Set cachedOutputs = outputs.files.files + !gradle.startParameter.offline || cachedOutputs.isEmpty() + || !cachedOutputs.every { it.exists() } + } +} + // Forward OreSpawn's opt-in qualification properties to disposable development // servers. These are build-only controls implemented by the exact released // OreSpawn jar; Mineralogy does not ship a second world-generation harness. @@ -191,7 +202,7 @@ configurations { dependencies { implementation "net.neoforged:neoforge:${project.neo_version}" - // NeoForge 26.1 uses official names in both development and production, so the + // NeoForge 26.2 uses official names in both development and production, so the // exact released OreSpawn artifact is suitable for ordinary runtime use. runtimeOnly(orespawnCoordinate) { transitive = false } orespawnRelease(orespawnCoordinate) { transitive = false } @@ -460,13 +471,16 @@ tasks.register('verifyMavenCoordinates') { tasks.register('verifyReleaseConfiguration') { group = 'verification' - description = 'Verifies the exact Mineralogy 26.1.2 NeoForge release identity.' + description = 'Verifies the exact Mineralogy 26.2 NeoForge release identity.' doLast { - if (project.mod_version != '6.1.2.2601022' + if (project.mod_version != '6.1.2.2602002' || project.mod_group != expectedMavenGroup - || project.minecraft_version != '26.1.2' - || project.neo_version != '26.1.2.94') { - throw new GradleException('Unexpected Mineralogy 26.1.2 NeoForge release identity') + || project.minecraft_version != '26.2' + || project.neo_version != '26.2.0.45-beta') { + throw new GradleException('Unexpected Mineralogy 26.2 NeoForge release identity') + } + if (project.findProperty('neogradle.subsystems.decompiler.enabled') != null) { + throw new GradleException('NeoForge 26.2 must retain its validated binary userdev path') } } } @@ -475,9 +489,9 @@ tasks.register('verifyReleaseDependencies') { group = 'verification' description = 'Resolves and verifies the exact released OreSpawn dependency.' doLast { - if (project.mod_version != '6.1.2.2601022' + if (project.mod_version != '6.1.2.2602002' || project.minecraft_version != project.mc_version - || project.mc_version != '26.1.2' + || project.mc_version != '26.2' || project.loader_name != 'neoforge' || project.loader_code != '2' || project.java_version != '25' @@ -486,9 +500,9 @@ tasks.register('verifyReleaseDependencies') { || project.curseforge_project_id != '240974') { throw new GradleException('Unexpected generic release dispatcher metadata') } - if (project.orespawn_version != '4.0.16.2601022' || + if (project.orespawn_version != '4.0.16.2602002' || project.orespawn_curse_project_id != '245586' || - project.orespawn_curse_file_id != '8809908') { + project.orespawn_curse_file_id != '8830635') { throw new GradleException('Unexpected OreSpawn release coordinates') } File artifact = configurations.orespawnRelease.resolvedConfiguration.resolvedArtifacts @@ -590,6 +604,10 @@ tasks.register('verifyReleaseArtifacts') { }) { throw new GradleException('Release jar contains a stale pre-1.21 plural data directory') } + def pack = new JsonSlurper().parse(zip.getInputStream(zip.getEntry('pack.mcmeta'))) + if (pack.pack?.max_format != 107 || pack.pack?.min_format != [107, 1]) { + throw new GradleException('Release jar does not use Minecraft 26.2 data format 107.1') + } def miningTagContracts = [ 'data/minecraft/tags/block/mineable/pickaxe.json': [1133, 1080], 'data/minecraft/tags/block/needs_iron_tool.json': [123, 120], @@ -616,7 +634,7 @@ tasks.register('verifyReleaseArtifacts') { def legacyItemModels = names.findAll { it ==~ /assets\/mineralogy\/models\/item\/[^\/]+\.json/ } def itemDefinitions = names.findAll { it ==~ /assets\/mineralogy\/items\/[^\/]+\.json/ } if (legacyItemModels.size() != 1144 || itemDefinitions.size() != 928) { - throw new GradleException('Release jar must contain 1,144 legacy item models and 928 NeoForge 26.1.2 item definitions') + throw new GradleException('Release jar must contain 1,144 legacy item models and 928 NeoForge 26.2 item definitions') } itemDefinitions.each { definitionName -> String id = definitionName.substring( @@ -627,7 +645,7 @@ tasks.register('verifyReleaseArtifacts') { def definition = new JsonSlurper().parse(zip.getInputStream(zip.getEntry(definitionName))) if (definition.model?.type != 'minecraft:model' || definition.model?.model != "mineralogy:item/${id}") { - throw new GradleException("Invalid NeoForge 26.1.2 item definition: ${definitionName}") + throw new GradleException("Invalid NeoForge 26.2 item definition: ${definitionName}") } } def blockModelText = names.findAll { @@ -702,7 +720,7 @@ tasks.register('verifyReleaseArtifacts') { ?.dimensions?.get('minecraft:overworld') if (!provider.rocks.values().every { it.min_y == -64 && it.max_y == 319 } || oil?.min_y != -48 || oil?.max_y != 48) { - throw new GradleException('Packaged provider does not use Minecraft 26.1.2 world heights') + throw new GradleException('Packaged provider does not use Minecraft 26.2 world heights') } if (provider.rocks['mineralogy:rock/minecraft/basalt']?.block != 'minecraft:basalt' || provider.rocks['mineralogy:rock/minecraft/tuff']?.block != 'minecraft:tuff' || @@ -719,7 +737,7 @@ tasks.register('verifyReleaseArtifacts') { dimension?.host_blocks == ['minecraft:stone', 'minecraft:deepslate'] && dimension?.host_tags == [] }) { - throw new GradleException('Packaged provider does not use the Minecraft 26.1.2 native-rock and deepslate contract') + throw new GradleException('Packaged provider does not use the Minecraft 26.2 native-rock and deepslate contract') } byte[] providerBytes = zip.getInputStream( zip.getEntry('data/mineralogy/orespawn/provider.json')).bytes @@ -741,7 +759,7 @@ tasks.register('verifyReleaseArtifacts') { 'data/mineralogy/advancement/mineralogy/all_the_rocks.json'))) if (allTheRocks.display?.icon?.id != 'mineralogy:basalt' || allTheRocks.display.icon.containsKey('item')) { - throw new GradleException('Custom advancement icon must use the Minecraft 26.1.2 item-stack id field') + throw new GradleException('Custom advancement icon must use the Minecraft 26.2 item-stack id field') } def verifyAdvancementPredicates = { advancement, String source -> advancement.criteria?.each { criterionName, criterion -> @@ -754,7 +772,7 @@ tasks.register('verifyReleaseArtifacts') { ? holderSet.isEmpty() || holderSet.any { !(it instanceof String) || it.isEmpty() } : !(holderSet instanceof String) || holderSet.isEmpty() }) { - throw new GradleException("Invalid Minecraft 26.1.2 item predicate in ${source}: ${criterionName}") + throw new GradleException("Invalid Minecraft 26.2 item predicate in ${source}: ${criterionName}") } } } @@ -765,7 +783,7 @@ tasks.register('verifyReleaseArtifacts') { }.each { entryName -> def advancement = new JsonSlurper().parse(zip.getInputStream(zip.getEntry(entryName))) if (advancement.sends_telemetry_event != false) { - throw new GradleException("Minecraft 26.1.2 recipe advancement must disable telemetry: ${entryName}") + throw new GradleException("Minecraft 26.2 recipe advancement must disable telemetry: ${entryName}") } if (advancement.criteria != null) verifyAdvancementPredicates(advancement, entryName) } @@ -836,6 +854,9 @@ tasks.register('verifyReleaseArtifacts') { data.group != 'mossy_cobblestone') { throw new GradleException("Mossy cobblestone override lost its vanilla recipe group: ${recipe}") } + if (recipe in ['furnace', 'brewing_stand'] && data.containsKey('category')) { + throw new GradleException("Minecraft 26.2 recipe must omit removed category: ${recipe}") + } } ['coast', 'sentry', 'vex'].each { template -> String recipeName = "${template}_armor_trim_smithing_template" @@ -848,7 +869,7 @@ tasks.register('verifyReleaseArtifacts') { || data.key?.get('#') != 'minecraft:diamond' || data.result?.id != result || data.result?.count != 2 - || data.category != 'misc' + || data.containsKey('category') || data.show_notification != true) { throw new GradleException("Invalid armor-trim cobblestone override: ${recipeName}") } @@ -861,10 +882,10 @@ tasks.register('verifyReleaseArtifacts') { if (recipe.endsWith('_stonecutting')) { if (!(data.result instanceof Map) || data.result.id == null || data.result.count != 2 || data.containsKey('count')) { - throw new GradleException("Invalid Minecraft 26.1.2 stonecutting result: ${recipe}") + throw new GradleException("Invalid Minecraft 26.2 stonecutting result: ${recipe}") } } else if (data.result?.id == null) { - throw new GradleException("Invalid Minecraft 26.1.2 slab result: ${recipe}") + throw new GradleException("Invalid Minecraft 26.2 slab result: ${recipe}") } } def families = ['andesite', 'basalt', 'diorite', 'granite', 'rhyolite', @@ -887,7 +908,11 @@ tasks.register('verifyReleaseArtifacts') { 'data/c/tags/item/paper.json': ['minecraft:paper'], 'data/forge/tags/item/paper.json': ['#c:paper'], 'data/c/tags/item/lamps/rock_salt.json': ['mineralogy:rocksaltlamp'], - 'data/forge/tags/item/lamps/rock_salt.json': ['#c:lamps/rock_salt'] + 'data/forge/tags/item/lamps/rock_salt.json': ['#c:lamps/rock_salt'], + 'data/c/tags/item/storage_blocks/sulfur.json': ['mineralogy:sulfur_block'], + 'data/c/tags/item/dusts/sulfur.json': ['mineralogy:sulfur_dust'], + 'data/forge/tags/item/storage_blocks/sulfur.json': ['#c:storage_blocks/sulfur'], + 'data/forge/tags/item/dusts/sulfur.json': ['#c:dusts/sulfur'] ].each { entryName, expectedValues -> def entry = zip.getEntry(entryName) def values = entry == null ? [] : new JsonSlurper().parse(zip.getInputStream(entry)).values @@ -895,6 +920,14 @@ tasks.register('verifyReleaseArtifacts') { throw new GradleException("Invalid canonical/compatibility ingredient tag: ${entryName}") } } + names.findAll { it.startsWith('data/mineralogy/recipe/') && it.endsWith('.json') }.each { entryName -> + String recipeText = zip.getInputStream(zip.getEntry(entryName)).withCloseable { stream -> + stream.getText('UTF-8') + } + if (recipeText.contains('minecraft:sulfur') || recipeText.contains('minecraft:cinnabar')) { + throw new GradleException("Mineralogy recipe aliases a native 26.2 material: ${entryName}") + } + } if (!families.every { names.contains("data/mineralogy/tags/block/stones/${it}.json".toString()) }) { throw new GradleException('Release jar must contain all 27 raw-rock family block tags') } @@ -938,7 +971,7 @@ tasks.register('verifyReleaseArtifacts') { def wallBlockstates = names.findAll { it ==~ /assets\/mineralogy\/blockstates\/.+_wall\.json/ } def tallWallModels = names.findAll { it ==~ /assets\/mineralogy\/models\/block\/.+_wall_side_tall\.json/ } if (wallBlockstates.size() != 108 || tallWallModels.size() != 108) { - throw new GradleException("Release jar must contain all 108 NeoForge 26.1.2 wall blockstates and tall-side models") + throw new GradleException("Release jar must contain all 108 NeoForge 26.2 wall blockstates and tall-side models") } } finally { diff --git a/docs/CONTENT_CONFIG.md b/docs/CONTENT_CONFIG.md index 4969e0c98..0f501ab2a 100644 --- a/docs/CONTENT_CONFIG.md +++ b/docs/CONTENT_CONFIG.md @@ -71,7 +71,7 @@ as levers, pistons, dispensers, droppers, and brewing stands. Setting it to and stone-crafting recipes while restoring their target-native ingredients. Rocks remain `stone`, retain their material-specific tags, and use exact Mineralogy slab, stair, and wall recipes. Chert and pumice remain historical -unconditional cobblestone equivalents in tag-backed recipes. The three 26.1.2 +unconditional cobblestone equivalents in tag-backed recipes. The three 26.2 armor-trim template duplication recipes restore exact vanilla cobblestone when the option is disabled, matching their native definitions. diff --git a/docs/DEVELOPER_GUIDE.md b/docs/DEVELOPER_GUIDE.md index 5b8717fc1..e3910de0e 100644 --- a/docs/DEVELOPER_GUIDE.md +++ b/docs/DEVELOPER_GUIDE.md @@ -40,14 +40,14 @@ families additionally use `cobblestone`; chert and pumice always retain that identity. Gypsum, chalk, rock salt, and both rock salt lamps retain their specialty aliases. -Minecraft 26.1.2's `minecraft:stone_crafting_materials` and +Minecraft 26.2's `minecraft:stone_crafting_materials` and `minecraft:stone_tool_materials` item tags include Mineralogy's dynamic union, so enabled Mineralogy rocks work in native tool recipes. NeoForge itself also uses `c:cobblestones/normal` in several higher-priority vanilla recipe overrides. Mineralogy therefore rebuilds that tag as well as the canonical `c:cobblestones`, compatibility, vanilla, and Mineralogy block and item tag membership after initial tag loading and every data reload. It preserves other -mods' members. Minecraft 26.1.2 retains live named holder sets rather than a +mods' members. Minecraft 26.2 retains live named holder sets rather than a public global ingredient-cache invalidator, so Mineralogy updates both each existing named holder set and every affected holder's tag membership in place; the holder-set invalidation callbacks make @@ -62,12 +62,12 @@ native aliases. The access transformer exposes only the package-private holder binding methods needed for that targeted update; it changes no game identity or recipe behavior by itself. -Minecraft 26.1.2 retains three additional configurable recipes: coast, sentry, and vex +Minecraft 26.2 retains three additional configurable recipes: coast, sentry, and vex armor-trim template duplication. They use the same dynamically rebound Mineralogy cobblestone union. Their vanilla advancements are intentionally untouched because those recipes unlock from owning the template, not from cobblestone. -Minecraft 26.1.2 also owns andesite, basalt, diorite, granite, tuff, and several +Minecraft 26.2 also owns andesite, basalt, diorite, granite, tuff, and several matching finishes. Mineralogy's family tags include both native and retained legacy identities. Five `data/minecraft/recipe/polished_*.json` overrides move the native polished-block route from 2x2 crafting to one exact native block plus @@ -124,7 +124,7 @@ material and finish so basalt cannot produce a different rock's slab or wall. ## Crafting Data -All Mineralogy recipes are native Minecraft/NeoForge 26.1.2 JSON under +All Mineralogy recipes are native Minecraft/NeoForge 26.2 JSON under `data/mineralogy/recipe/`. Run `scripts/generate-recipes.ps1` after changing the recipe matrix; it generates the 27 stone families and global recipes, the native slab/stonecutting overrides and compatibility conversions, and the five @@ -134,7 +134,7 @@ advancement with the same NeoForge conditions and the same exact-item or family-tag material predicate as the recipe. Unlocks use direct inventory ingredients instead of listening to other recipe unlocks, which would recursively reveal an entire construction tree. Polishing uses Minecraft -26.1.2's advancement requirements matrix to require the matching source plus +26.2's advancement requirements matrix to require the matching source plus accepted sand; manually crafting a recipe is the target-native fallback for Forge's delayed crafting-output inventory trigger. Rock-furnace advancements use the matching slab-family tag as their sole material criterion. They @@ -161,14 +161,14 @@ The legacy `GENERATE_*` flags can remove registrations on the next start. The new issue-121 switches only change creative visibility and Mineralogy-owned recipes, so existing content remains loadable. -NeoForge 26.1 converts pre-flattening chunks lazily. Required Mixins expand +NeoForge 26.2 converts pre-flattening chunks lazily. Required Mixins expand Minecraft's fixed legacy state tables before conversion, and the selected-world hook installs the complete saved block mapping before Mojang's data fixer. It reinstalls that mapping after the client enumerates other old saves, normalizes legacy rock-furnace tile IDs, retains sidecar recovery, and protects populated chunks from cross-boundary feature writes. The Mixins target exact owners and descriptors and fail startup if a required injection point cannot be found. -Minecraft 26.1's four-argument chunk upgrader is intercepted before and after +Minecraft 26.2's four-argument chunk upgrader is intercepted before and after conversion, and the discovery pass indexes both historical root `region` files and `dimensions/minecraft/overworld/region`. The obsolete JavaScript coremod is deliberately absent. Validate both previously @@ -178,9 +178,9 @@ reobfuscated jar; a development launch alone cannot prove this path. ## Building The build uses NeoGradle 7.1.38 and the Gradle 9.2.1 wrapper on Java 25, -with an exact Temurin 25.0.3+9 toolchain for production and test bytecode. The -API-complete decompiler path is enabled because NeoForge 26.1.2's combined -binary omits public biome accessors required by production sources: +with an exact Temurin 25.0.3+9 toolchain for production and test bytecode. +NeoForge 26.2 uses the validated binary userdev path; the temporary 26.1.2 +source-decompiler workaround is deliberately absent: ```powershell $env:JAVA_HOME='path-to-Temurin-25.0.3+9' @@ -195,5 +195,5 @@ OreSpawn in a launcher-like NeoForge installation. The normal jar packages this guide under `META-INF/mineralogy/docs/`. The complete release version is `Major.Minor.Bug.Target`; see -[Mineralogy Versioning](VERSIONS.md). This branch validates target `2601022` -for Minecraft 26.1.2 NeoForge and does not append CI build numbers. +[Mineralogy Versioning](VERSIONS.md). This branch validates target `2602002` +for Minecraft 26.2 NeoForge and does not append CI build numbers. diff --git a/docs/PLAYER_GUIDE.md b/docs/PLAYER_GUIDE.md index 1e28e15f2..6485be6fb 100644 --- a/docs/PLAYER_GUIDE.md +++ b/docs/PLAYER_GUIDE.md @@ -2,8 +2,8 @@ ## Installing -Mineralogy 6 needs Minecraft 26.1.2, NeoForge 26.1.2.94, and OreSpawn -4.0.16.2601022. Do not mix this NeoForge jar with the separate Forge build. +Mineralogy 6 needs Minecraft 26.2, NeoForge 26.2.0.45-beta, and OreSpawn +4.0.16.2602002. Do not mix this NeoForge jar with the separate Forge build. Install matching Mineralogy and OreSpawn jars on both clients and servers. Do not open a world containing Mineralogy blocks without Mineralogy installed. @@ -19,7 +19,7 @@ Cyano/`LEGACY` engine with their established family order and layer settings. It does not silently convert old terrain to Stable Layers. Back up an important world before changing its profile or upgrading mods. -On the first 26.1.2 start, Mineralogy recognizes the old saved registry and +On the first 26.2 start, Mineralogy recognizes the old saved registry and protects existing Overworld chunks while Minecraft converts them to flattened block states. Rock furnaces are converted when their chunk is first loaded; their inventory and cooking progress are retained. Old vanilla tile IDs are @@ -90,7 +90,7 @@ Its **Rock Settings** screen provides four altitude controls: - **Minimum Y** (`min_y`) and **Maximum Y** (`max_y`) are inclusive hard limits. The rock cannot replace terrain outside them. -Minecraft 26.1.2 accepts Y `-64` through `319`; Depth Spread accepts `1` through +Minecraft 26.2 accepts Y `-64` through `319`; Depth Spread accepts `1` through `512`. The saved fields are independent of the rock's geological family, overall weight, and geome weights, which also affect where it is selected. @@ -118,7 +118,7 @@ terrain replacement through each dimension's `host_blocks` and `host_tags`. The packaged Mineralogy profile initially uses `minecraft:stone` and `minecraft:deepslate` in the Overworld. -The terrain-host list is not exposed by OreSpawn's 26.1.2 graphical editor. Stop +The terrain-host list is not exposed by OreSpawn's 26.2 graphical editor. Stop Minecraft or the server before editing the JSON. For defaults inherited by worlds created afterward, edit: @@ -152,11 +152,11 @@ each natural terrain block that Mineralogy rock may replace: ``` Use `host_tags` when an OreSpawn/pack-provided group is more appropriate; on -Minecraft 26.1.2 these resolve through target-native block tags. Exact +Minecraft 26.2 these resolve through target-native block tags. Exact `host_blocks` entries are the clearest choice for one modded stone. -Minecraft 26.1.2 matches a `host_blocks` entry by flattened block registry +Minecraft 26.2 matches a `host_blocks` entry by flattened block registry identity. Add only natural base-terrain blocks, not machines, containers, or construction blocks. Restart after editing. The change affects only chunks generated afterward; @@ -165,11 +165,11 @@ OreSpawn never retro-generates Mineralogy rock strata into existing chunks. ### Enabling Mineralogy Geology In Another Dimension OreSpawn can apply Mineralogy rocks to a stone-based mod dimension without a -separate Mineralogy dimension option. Minecraft 26.1.2 uses the dimension +separate Mineralogy dimension option. Minecraft 26.2 uses the dimension type's registered ID. For example, use `examplemod:moon` when that is the ID documented by the installed dimension mod. -The 26.1.2 graphical editor does not expose terrain-dimension or rock-membership +The 26.2 graphical editor does not expose terrain-dimension or rock-membership fields. Stop Minecraft or the server and edit the appropriate OreSpawn JSON: `config/orespawn-worldgen.json` for defaults inherited by future worlds, or `/serverconfig/orespawn-worldgen.json` for an established world. diff --git a/docs/PROVIDER.md b/docs/PROVIDER.md index 18aeb8f48..3c92e0201 100644 --- a/docs/PROVIDER.md +++ b/docs/PROVIDER.md @@ -14,7 +14,7 @@ The exact bytes from the installed build are exported as - Provider schema 4, mod ID `mineralogy`, and provider revision 3. - 32 enabled rock rules across the four geological families. - Sulfur, phosphorous, and nitrate ore rules. -- Minecraft 26.1.2 heights `-64` through `319` and Overworld-only terrain defaults. +- Minecraft 26.2 heights `-64` through `319` and Overworld-only terrain defaults. - Minecraft blocks for granite, diorite, andesite, basalt, and tuff. Worldgen aliases map the five matching historical Mineralogy rock IDs to their native outputs, while all historical Mineralogy blocks remain registered for old @@ -82,7 +82,7 @@ that same dimension ID to each desired rock rule's `dimensions` array. A rock without `dimensions` is Overworld-only. A configured custom dimension is disabled during baking when no valid rock rules include it. -Minecraft 26.1.2 uses the registered dimension-type ID, such as +Minecraft 26.2 uses the registered dimension-type ID, such as `examplemod:moon`; consult the dimension mod's documentation for its exact ID. Rock membership makes different stone sets possible per dimension. To use different altitude settings for the same output block, define unique rock rule @@ -90,7 +90,7 @@ IDs with different `depth_peak`, `depth_spread`, `min_y`, or `max_y` values and non-overlapping dimension lists. Duplicate output states within one dimension are rejected. -The 26.1.2 editor does not expose terrain-dimension or rock-membership fields, so +The 26.2 editor does not expose terrain-dimension or rock-membership fields, so players edit the stopped world's saved profile and pack authors may provide global defaults or a complete provider override. Changes affect newly generated chunks only. @@ -112,6 +112,6 @@ intends to replace the whole packaged Mineralogy provider; it is unnecessary for an ordinary per-world host-list change and does not rewrite established world profiles. -On Minecraft 26.1.2, terrain hosts are baked as flattened block identities. +On Minecraft 26.2, terrain hosts are baked as flattened block identities. Changes affect only newly generated chunks because Mineralogy strata are never retro-generated. diff --git a/docs/README.md b/docs/README.md index 9acb08762..969f6569b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Mineralogy Guide -Mineralogy 6 for Minecraft 26.1.2 supplies rock, mineral, construction, and +Mineralogy 6 for Minecraft 26.2 supplies rock, mineral, construction, and crude-oil content to OreSpawn 4. OreSpawn is the only terrain and deposit engine. diff --git a/docs/VERSIONS.md b/docs/VERSIONS.md index c5c2c4811..6e2680c03 100644 --- a/docs/VERSIONS.md +++ b/docs/VERSIONS.md @@ -13,10 +13,10 @@ The first three components are the **functional version**. Mineralogy `6.1.2` means major generation 6, minor release 1, and bug revision 2. The fourth component identifies the target build. The complete version for -this Minecraft 26.1.2 NeoForge release is therefore: +this Minecraft 26.2 NeoForge release is therefore: ```text -6.1.2.2601022 +6.1.2.2602002 ``` This expanded numeric form is compatible with Maven version ordering, but it @@ -25,7 +25,7 @@ components. The release tag is exactly the complete four-component version, with no redundant Minecraft-version prefix. For this branch the tag is therefore -`6.1.2.2601022`, not `26.1.2-6.1.2.2601022`. The Target already makes tags unique +`6.1.2.2602002`, not `26.2-6.1.2.2602002`. The Target already makes tags unique across Minecraft versions and loaders. ## Reading the target component @@ -63,10 +63,10 @@ minor digits, and all remaining digits for the Minecraft major version. | 1.21.11 | NeoForge | `121112` | `6.1.2.121112` | | 26.1.2 | Forge | `2601021` | `6.1.2.2601021` | | 26.1.2 | NeoForge | `2601022` | `6.1.2.2601022` | -| 26.2 | Forge | `2602001` | `6.0.0.2602001` | -| 26.2 | NeoForge | `2602002` | `6.0.0.2602002` | +| 26.2 | Forge | `2602001` | `6.1.2.2602001` | +| 26.2 | NeoForge | `2602002` | `6.1.2.2602002` | -The 26.1.2 NeoForge row records this branch's current release. The other rows illustrate +The 26.2 NeoForge row records this branch's current release. The other rows illustrate target encoding or earlier releases; they do not claim that later Minecraft targets already contain the same functional changes. @@ -131,6 +131,7 @@ Minecraft 1.20.6 / Forge / Mineralogy 6.1.2.120061 Minecraft 1.21.1 / NeoForge / Mineralogy 6.1.2.121012 Minecraft 1.21.11 / NeoForge / Mineralogy 6.1.2.121112 Minecraft 26.1.2 / NeoForge / Mineralogy 6.1.2.2601022 +Minecraft 26.2 / NeoForge / Mineralogy 6.1.2.2602002 ``` Minecraft and loader APIs may require different internal code without changing @@ -162,8 +163,8 @@ excluding Mineralogy 7. Minecraft and loader metadata still decide whether a particular jar can load on the current game. Mineralogy 6 also requires OreSpawn `[4.0.6,5.0.0)`. OreSpawn uses the same -target calculation, so the matching Minecraft 26.1.2 NeoForge release used for -this candidate is `4.0.16.2601022`. The dependency range deliberately describes the supported +target calculation, so the matching Minecraft 26.2 NeoForge release used for +this candidate is `4.0.16.2602002`. The dependency range deliberately describes the supported functional OreSpawn generation; NeoForge still prevents jars for another Minecraft target from loading together. @@ -176,7 +177,7 @@ feature generation, not the exact jar. The Gradle build reads the complete version from `mod_version`, verifies that it has four numeric components, and checks that its Target matches the declared Minecraft version and NeoForge loader. CI build numbers are not appended. For this -branch, published metadata and artifacts therefore use `6.1.2.2601022`. +branch, published metadata and artifacts therefore use `6.1.2.2602002`. Every release note should state: diff --git a/gradle.properties b/gradle.properties index 9433b728a..427a2aad0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,9 +5,7 @@ org.gradle.daemon=false org.gradle.configuration-cache=false org.gradle.caching=true org.gradle.parallel=false -neogradle.subsystems.decompiler.enabled=true - -mod_version=6.1.2.2601022 +mod_version=6.1.2.2602002 mod_group=zone.moddev.mc.mineralogy mod_group_id=zone.moddev.mc.mineralogy mod_id=mineralogy @@ -17,20 +15,20 @@ mod_authors=Cyanobacterium, SkyBlade1978, JRIwanek mod_description=Fills the world with real-world rocks. # Release metadata consumed by the generic dispatcher. -minecraft_version=26.1.2 -mc_version=26.1.2 -minecraft_version_range=[26.1.2] +minecraft_version=26.2 +mc_version=26.2 +minecraft_version_range=[26.2] loader_name=neoforge loader_code=2 -neo_version=26.1.2.94 -neo_version_range=[26.1.2.94,26.1.3) +neo_version=26.2.0.45-beta +neo_version_range=[26.2.0.45-beta,26.2.1) java_version=25 java_toolchain_version=25.0.3+9 java_setup_version=25.0.3+9.0.LTS gradle_java_version=25 curseforge_project_id=240974 -orespawn_version=4.0.16.2601022 +orespawn_version=4.0.16.2602002 orespawn_curse_project_id=245586 -orespawn_curse_file_id=8809908 -orespawn_sha256=4F6612B89FC65E4860E962E8EA45CC03B752330060B3362112EBEBC7AA9C2E6C +orespawn_curse_file_id=8830635 +orespawn_sha256=16DFD59B5083BB1F7FE399091AC9778F9D10F397FE214865C937F00D1C20625A diff --git a/resourcepack/x128/pack.mcmeta b/resourcepack/x128/pack.mcmeta index ce750e87a..25e09dccd 100644 --- a/resourcepack/x128/pack.mcmeta +++ b/resourcepack/x128/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 84, - "min_format": 84, + "max_format": 88, + "min_format": 88, "description": "Minecraft Mineralogy\n-FoxNekitsune & DrCyano" } } diff --git a/resourcepack/x16/pack.mcmeta b/resourcepack/x16/pack.mcmeta index ce750e87a..25e09dccd 100644 --- a/resourcepack/x16/pack.mcmeta +++ b/resourcepack/x16/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 84, - "min_format": 84, + "max_format": 88, + "min_format": 88, "description": "Minecraft Mineralogy\n-FoxNekitsune & DrCyano" } } diff --git a/resourcepack/x32/pack.mcmeta b/resourcepack/x32/pack.mcmeta index a3293412d..f99922831 100644 --- a/resourcepack/x32/pack.mcmeta +++ b/resourcepack/x32/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 84, - "min_format": 84, + "max_format": 88, + "min_format": 88, "description": "Minecraft Mineralogy\n-Fox Nekitsune & DrCyano" } } diff --git a/resourcepack/x64/pack.mcmeta b/resourcepack/x64/pack.mcmeta index a3293412d..f99922831 100644 --- a/resourcepack/x64/pack.mcmeta +++ b/resourcepack/x64/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 84, - "min_format": 84, + "max_format": 88, + "min_format": 88, "description": "Minecraft Mineralogy\n-Fox Nekitsune & DrCyano" } } diff --git a/scripts/generate-locales.ps1 b/scripts/generate-locales.ps1 index e7bbb4960..23ac8147c 100644 --- a/scripts/generate-locales.ps1 +++ b/scripts/generate-locales.ps1 @@ -53,4 +53,4 @@ $actual = @(Get-ChildItem -LiteralPath $targetRoot -Filter '*.json' | Sort-Objec if ($actual.Count -ne 17) { throw "Expected exactly 17 generated locale files, found $($actual.Count)" } -Write-Output 'Generated 17 reviewed Mineralogy 26.1.2 JSON locales with 938 ordered keys each.' +Write-Output 'Generated 17 reviewed Mineralogy 26.2 JSON locales with 938 ordered keys each.' diff --git a/scripts/generate-recipes.ps1 b/scripts/generate-recipes.ps1 index ed2022029..aca0357a8 100644 --- a/scripts/generate-recipes.ps1 +++ b/scripts/generate-recipes.ps1 @@ -27,7 +27,7 @@ $colors = @( 'gray', 'pink', 'lime', 'yellow', 'light_blue', 'magenta', 'orange', 'white' ) -# Minecraft owns these full-block identities in 26.1.2. Mineralogy keeps its +# Minecraft owns these full-block identities in 26.2. Mineralogy keeps its # legacy blocks registered, but recipes may accept either identity where doing # so cannot compete with a native recipe. $nativeFullBlocks = @{ @@ -146,7 +146,7 @@ function AdvancementPredicate([object] $ingredient) { if ($null -ne $ingredient.PSObject.Properties['items']) { return [ordered]@{ items = $ingredient.items } } - throw "Cannot convert recipe ingredient into a Minecraft 26.1.2 advancement predicate" + throw "Cannot convert recipe ingredient into a Minecraft 26.2 advancement predicate" } function OreIngredient([string] $ore) { @@ -172,7 +172,7 @@ function OreIngredient([string] $ore) { $finish = if ($Matches[2]) { '/' + (Convert-CamelToSnake $Matches[2]) } else { '' } return "#mineralogy:slabs/$family$finish" } - throw "No Minecraft 26.1.2 tag mapping for legacy OreDictionary key $ore" + throw "No Minecraft 26.2 tag mapping for legacy OreDictionary key $ore" } function Convert-CamelToSnake([string] $value) { @@ -236,16 +236,20 @@ function VanillaShapedRecipe( [string[]] $pattern, [System.Collections.IDictionary] $key, [string] $result, - [int] $count = 1 + [int] $count = 1, + [bool] $includeCategory = $true ) { - return [ordered]@{ + $recipe = [ordered]@{ type = 'minecraft:crafting_shaped' - category = VanillaCraftingCategoryForResult $result - pattern = $pattern - key = $key - result = VanillaResult $result $count - show_notification = $true } + if ($includeCategory) { + $recipe['category'] = VanillaCraftingCategoryForResult $result + } + $recipe['pattern'] = $pattern + $recipe['key'] = $key + $recipe['result'] = VanillaResult $result $count + $recipe['show_notification'] = $true + return $recipe } function VanillaShapelessRecipe( @@ -1093,12 +1097,12 @@ function Write-CobblestoneRecipeOverrides() { $fallbackTools = '#minecraft:stone_tool_materials' Write-ConditionalMinecraftRecipe 'furnace' $condition ` - (VanillaShapedRecipe @('###', '# #', '###') ([ordered]@{ '#' = $enabledCrafting }) 'minecraft:furnace') ` + (VanillaShapedRecipe @('###', '# #', '###') ([ordered]@{ '#' = $enabledCrafting }) 'minecraft:furnace' 1 $false) ` (VanillaShapedRecipe @('###', '# #', '###') ([ordered]@{ '#' = $fallbackCrafting }) 'minecraft:furnace') Write-ConditionalMinecraftRecipe 'brewing_stand' $condition ` (VanillaShapedRecipe @(' B ', '###') ([ordered]@{ B = ItemIngredient 'minecraft:blaze_rod'; '#' = $enabledCrafting - }) 'minecraft:brewing_stand') ` + }) 'minecraft:brewing_stand' 1 $false) ` (VanillaShapedRecipe @(' B ', '###') ([ordered]@{ B = ItemIngredient 'minecraft:blaze_rod'; '#' = $fallbackCrafting }) 'minecraft:brewing_stand') @@ -1184,7 +1188,7 @@ function Write-CobblestoneRecipeOverrides() { '#' = ItemIngredient 'minecraft:diamond' C = $enabledCobblestone S = ItemIngredient $templateItem - }) $templateItem 2 + }) $templateItem 2 $false $fallbackRecipe = VanillaShapedRecipe @('#S#', '#C#', '###') ([ordered]@{ '#' = ItemIngredient 'minecraft:diamond' C = ItemIngredient 'minecraft:cobblestone' @@ -1381,4 +1385,4 @@ $advancementCount = Synchronize-AdvancementConditions if ($advancementCount -ne $expectedTargetRecipeCount) { throw "Expected $expectedTargetRecipeCount recipe advancements, found $advancementCount" } -Write-Output "Generated $expectedRecipeCount crafting recipe JSON files, retained 28 target-native smelting recipes, created $createdAdvancements missing recipe advancements, and conditioned $advancementCount Minecraft 26.1.2 recipe advancements." +Write-Output "Generated $expectedRecipeCount crafting recipe JSON files, retained 28 target-native smelting recipes, created $createdAdvancements missing recipe advancements, and conditioned $advancementCount Minecraft 26.2 recipe advancements." diff --git a/src/main/java/zone/moddev/mc/mineralogy/compat/CobblestoneTagPolicy.java b/src/main/java/zone/moddev/mc/mineralogy/compat/CobblestoneTagPolicy.java index 2dc066a89..08d78a265 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/compat/CobblestoneTagPolicy.java +++ b/src/main/java/zone/moddev/mc/mineralogy/compat/CobblestoneTagPolicy.java @@ -22,7 +22,7 @@ import zone.moddev.mc.mineralogy.data.Material; import zone.moddev.mc.mineralogy.data.MaterialData; -/** Applies the legacy cobblestone option to NeoForge 26.1 tags. */ +/** Applies the legacy cobblestone option to NeoForge 26.2 tags. */ public final class CobblestoneTagPolicy { private static final Identifier COMMON_COBBLESTONES = id("c", "cobblestones"); private static final Identifier COMMON_NORMAL_COBBLESTONES = id("c", "cobblestones/normal"); @@ -75,7 +75,7 @@ public static void apply(HolderLookup.Provider access) { updateTag(itemRegistry, Registries.ITEM, STONE_TOOL_MATERIALS, configuredItems, enabled, "chert", "pumice"); - Mineralogy.LOGGER.debug("Applied NeoForge 26.1 cobblestone policy: enabled={}, rocks={}, " + Mineralogy.LOGGER.debug("Applied NeoForge 26.2 cobblestone policy: enabled={}, rocks={}, " + "unionItems={}, commonItems={}, craftingItems={}, toolItems={}", enabled, configuredItems.size(), size(itemRegistry, Registries.ITEM, MINERALOGY_COBBLESTONE), size(itemRegistry, Registries.ITEM, COMMON_COBBLESTONES), diff --git a/src/main/java/zone/moddev/mc/mineralogy/init/RegistrationProperties.java b/src/main/java/zone/moddev/mc/mineralogy/init/RegistrationProperties.java index 27766c5d9..b707063d5 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/init/RegistrationProperties.java +++ b/src/main/java/zone/moddev/mc/mineralogy/init/RegistrationProperties.java @@ -10,7 +10,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour; /** - * Applies the stable registry identity before Minecraft 26.1.2 constructs an + * Applies the stable registry identity before Minecraft 26.2 constructs an * item or block. The target derives description and loot identities during * construction, so assigning the registry entry afterward is too late. */ diff --git a/src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java b/src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java index 187c09ca6..274790459 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java +++ b/src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java @@ -25,7 +25,7 @@ public InteractionResult useOn(UseOnContext context) { boolean canUse = BoneMealItem.applyBonemeal(context.getItemInHand(), world, target, player); if (canUse) { - // Minecraft 26.1 binds item components after registry objects are + // Minecraft 26.2 binds item components after registry objects are // constructed, so helper stacks must be created lazily during play. ItemStack phantomBonemeal = new ItemStack(Items.BONE_MEAL, 27); for (int dx = -2; dx <= 2; dx++) { diff --git a/src/main/java/zone/moddev/mc/mineralogy/mixin/OreSpawnEarlyTagCompatibilityMixin.java b/src/main/java/zone/moddev/mc/mineralogy/mixin/OreSpawnEarlyTagCompatibilityMixin.java index 3b8e8fe77..e18fd9921 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/mixin/OreSpawnEarlyTagCompatibilityMixin.java +++ b/src/main/java/zone/moddev/mc/mineralogy/mixin/OreSpawnEarlyTagCompatibilityMixin.java @@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** - * Minecraft 26.1.2 throws when a block tag is queried before the first tag + * Minecraft 26.2 throws when a block tag is queried before the first tag * load. OreSpawn 4.0.16 can make that query during common setup when an older * global profile contains tag-backed ore hosts. Defer those hosts as an empty * early result; OreSpawn rebakes the same unchanged profile after the world's diff --git a/src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java b/src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java index 9e7149834..535d1cd05 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java +++ b/src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java @@ -8,7 +8,7 @@ import zone.moddev.mc.mineralogy.compat.CobblestoneTagPolicy; /** - * Rebind the affected named sets immediately after Minecraft 26.1.2 commits + * Rebind the affected named sets immediately after Minecraft 26.2 commits * pending tags and static components, which also covers every later /reload. */ @Mixin(ReloadableServerResources.class) diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index e0323d180..7bbb1c7bb 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,4 +1,4 @@ -# Minecraft 26.1.2 ingredients retain live HolderSet references. Expose only +# Minecraft 26.2 ingredients retain live HolderSet references. Expose only # the two binding operations needed to keep named-set contents and individual # holder membership synchronized after Mineralogy applies its runtime policy. public net.minecraft.core.Holder$Reference bindTags(Ljava/util/Collection;)V diff --git a/src/main/resources/data/minecraft/recipe/brewing_stand.json b/src/main/resources/data/minecraft/recipe/brewing_stand.json index 814854fd8..ed1098f2c 100644 --- a/src/main/resources/data/minecraft/recipe/brewing_stand.json +++ b/src/main/resources/data/minecraft/recipe/brewing_stand.json @@ -1,6 +1,5 @@ { "type": "minecraft:crafting_shaped", - "category": "misc", "pattern": [ " B ", "###" diff --git a/src/main/resources/data/minecraft/recipe/coast_armor_trim_smithing_template.json b/src/main/resources/data/minecraft/recipe/coast_armor_trim_smithing_template.json index 2b8e1a104..1749ce080 100644 --- a/src/main/resources/data/minecraft/recipe/coast_armor_trim_smithing_template.json +++ b/src/main/resources/data/minecraft/recipe/coast_armor_trim_smithing_template.json @@ -1,6 +1,5 @@ { "type": "minecraft:crafting_shaped", - "category": "misc", "pattern": [ "#S#", "#C#", diff --git a/src/main/resources/data/minecraft/recipe/furnace.json b/src/main/resources/data/minecraft/recipe/furnace.json index ad43e6fea..dc12f3c00 100644 --- a/src/main/resources/data/minecraft/recipe/furnace.json +++ b/src/main/resources/data/minecraft/recipe/furnace.json @@ -1,6 +1,5 @@ { "type": "minecraft:crafting_shaped", - "category": "misc", "pattern": [ "###", "# #", diff --git a/src/main/resources/data/minecraft/recipe/sentry_armor_trim_smithing_template.json b/src/main/resources/data/minecraft/recipe/sentry_armor_trim_smithing_template.json index 95c849330..02efd9b29 100644 --- a/src/main/resources/data/minecraft/recipe/sentry_armor_trim_smithing_template.json +++ b/src/main/resources/data/minecraft/recipe/sentry_armor_trim_smithing_template.json @@ -1,6 +1,5 @@ { "type": "minecraft:crafting_shaped", - "category": "misc", "pattern": [ "#S#", "#C#", diff --git a/src/main/resources/data/minecraft/recipe/vex_armor_trim_smithing_template.json b/src/main/resources/data/minecraft/recipe/vex_armor_trim_smithing_template.json index 3ce493bce..425868581 100644 --- a/src/main/resources/data/minecraft/recipe/vex_armor_trim_smithing_template.json +++ b/src/main/resources/data/minecraft/recipe/vex_armor_trim_smithing_template.json @@ -1,6 +1,5 @@ { "type": "minecraft:crafting_shaped", - "category": "misc", "pattern": [ "#S#", "#C#", diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 6b3c09d3d..e52b88f9f 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,9 +1,9 @@ { "pack": { "description": "mineralogy resources", - "max_format": 101, + "max_format": 107, "min_format": [ - 101, + 107, 1 ] } diff --git a/src/oilCompatibilityTest/resources/META-INF/neoforge.mods.toml b/src/oilCompatibilityTest/resources/META-INF/neoforge.mods.toml index b593df62a..4a6b7c95a 100644 --- a/src/oilCompatibilityTest/resources/META-INF/neoforge.mods.toml +++ b/src/oilCompatibilityTest/resources/META-INF/neoforge.mods.toml @@ -9,13 +9,13 @@ description='''Disposable runtime fixture for Mineralogy crude-oil coexistence v [[dependencies.poweradvantage]] modId="neoforge" type="required" -versionRange="[26.1.2.94,26.1.3)" +versionRange="[26.2.0.45-beta,26.2.1)" ordering="NONE" side="BOTH" [[dependencies.poweradvantage]] modId="mineralogy" type="required" -versionRange="[6.1.2.2601022]" +versionRange="[6.1.2.2602002]" ordering="AFTER" side="BOTH" diff --git a/src/oilCompatibilityTest/resources/pack.mcmeta b/src/oilCompatibilityTest/resources/pack.mcmeta index 228f5b815..0483a956d 100644 --- a/src/oilCompatibilityTest/resources/pack.mcmeta +++ b/src/oilCompatibilityTest/resources/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { "description": "Mineralogy historical oil compatibility fixture", - "max_format": 101, - "min_format": [101, 1] + "max_format": 107, + "min_format": [107, 1] } } diff --git a/src/recipeIntegrationTest/resources/META-INF/neoforge.mods.toml b/src/recipeIntegrationTest/resources/META-INF/neoforge.mods.toml index b1f01dba8..24b96b284 100644 --- a/src/recipeIntegrationTest/resources/META-INF/neoforge.mods.toml +++ b/src/recipeIntegrationTest/resources/META-INF/neoforge.mods.toml @@ -8,13 +8,13 @@ displayName="Mineralogy Recipe Integration Probe" [[dependencies.mineralogyrecipeprobe]] modId="neoforge" type="required" -versionRange="[26.1.2.94,26.1.3)" +versionRange="[26.2.0.45-beta,26.2.1)" ordering="NONE" side="BOTH" [[dependencies.mineralogyrecipeprobe]] modId="mineralogy" type="required" -versionRange="[6.1.2.2601022]" +versionRange="[6.1.2.2602002]" ordering="AFTER" side="BOTH" diff --git a/src/recipeIntegrationTest/resources/pack.mcmeta b/src/recipeIntegrationTest/resources/pack.mcmeta index cd2de0b08..3a3040c65 100644 --- a/src/recipeIntegrationTest/resources/pack.mcmeta +++ b/src/recipeIntegrationTest/resources/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { "description": "Mineralogy recipe integration fixture", - "max_format": 101, - "min_format": [101, 1] + "max_format": 107, + "min_format": [107, 1] } } diff --git a/src/test/java/zone/moddev/mc/mineralogy/LocalizationQualityTest.java b/src/test/java/zone/moddev/mc/mineralogy/LocalizationQualityTest.java index d18be867b..47e89af67 100644 --- a/src/test/java/zone/moddev/mc/mineralogy/LocalizationQualityTest.java +++ b/src/test/java/zone/moddev/mc/mineralogy/LocalizationQualityTest.java @@ -23,7 +23,7 @@ import static org.junit.Assert.*; -/** Quality policy for the reviewed 26.1.2 JSON localization inventory. */ +/** Quality policy for the reviewed 26.2 JSON localization inventory. */ public class LocalizationQualityTest { private static final File LANG_DIR = new File("src/main/resources/assets/mineralogy/lang"); private static final Set ENGLISH_LOCALES = new HashSet(Arrays.asList( diff --git a/src/test/java/zone/moddev/mc/mineralogy/ResourceContractTest.java b/src/test/java/zone/moddev/mc/mineralogy/ResourceContractTest.java index 3803bb7d1..d339aac43 100644 --- a/src/test/java/zone/moddev/mc/mineralogy/ResourceContractTest.java +++ b/src/test/java/zone/moddev/mc/mineralogy/ResourceContractTest.java @@ -50,7 +50,7 @@ public void providerUsesOreSpawnFourAndOwnsNoVanillaGeneration() throws Exceptio assertFalse(text.contains("metadata")); assertTrue(text.contains("minecraft:deepslate")); assertTrue(text.contains("\"host_blocks\"")); - assertFalse("NeoForge 26.1 common setup must not resolve unbound host tags", + assertFalse("NeoForge 26.2 common setup must not resolve unbound host tags", text.contains("minecraft:stone_ore_replaceables") || text.contains("minecraft:deepslate_ore_replaceables")); for (Map.Entry entry : provider.getAsJsonObject("rocks").entrySet()) { @@ -454,15 +454,15 @@ public void allSeventeenLocalesHaveOrdered938KeyParity() throws Exception { } @Test - public void neoForge261ResourcesRetainNativeWallsTagsAndPackFormats() throws Exception { + public void neoForge262ResourcesRetainNativeWallsTagsAndPackFormats() throws Exception { JsonObject pack = json(new File(ROOT, "pack.mcmeta")); - assertEquals(101, pack.getAsJsonObject("pack").get("max_format").getAsInt()); + assertEquals(107, pack.getAsJsonObject("pack").get("max_format").getAsInt()); JsonArray dataMinimum = pack.getAsJsonObject("pack").getAsJsonArray("min_format"); - assertEquals(101, dataMinimum.get(0).getAsInt()); + assertEquals(107, dataMinimum.get(0).getAsInt()); assertEquals(1, dataMinimum.get(1).getAsInt()); JsonObject resourcePack = json(new File("resourcepack/x16/pack.mcmeta")); - assertEquals(84, resourcePack.getAsJsonObject("pack").get("min_format").getAsInt()); - assertEquals(84, resourcePack.getAsJsonObject("pack").get("max_format").getAsInt()); + assertEquals(88, resourcePack.getAsJsonObject("pack").get("min_format").getAsInt()); + assertEquals(88, resourcePack.getAsJsonObject("pack").get("max_format").getAsInt()); File blockstates = new File(ROOT, "assets/mineralogy/blockstates"); File[] wallStates = blockstates.listFiles((dir, name) -> name.endsWith("_wall.json")); @@ -529,6 +529,9 @@ public void neoForge261ResourcesRetainNativeWallsTagsAndPackFormats() throws Exc assertEquals(id, "minecraft:" + id, enabled.getAsJsonObject("result").get("id").getAsString()); assertEquals(id, 2, enabled.getAsJsonObject("result").get("count").getAsInt()); + assertFalse(id, enabled.has("category")); + assertTrue(id, enabled.has("show_notification")); + assertTrue(id, enabled.get("show_notification").getAsBoolean()); } File[] stonecutting = new File(ROOT, "data/mineralogy/recipe") .listFiles((dir, name) -> name.contains("stonecutting")); @@ -537,14 +540,14 @@ public void neoForge261ResourcesRetainNativeWallsTagsAndPackFormats() throws Exc } @Test - public void integrationFixturesUseDataFormat101AndSingularDataDirectories() throws Exception { + public void integrationFixturesUseDataFormat107AndSingularDataDirectories() throws Exception { for (String sourceSet : Arrays.asList("recipeIntegrationTest", "oilCompatibilityTest")) { File fixtureRoot = new File("src/" + sourceSet + "/resources"); JsonObject pack = json(new File(fixtureRoot, "pack.mcmeta")); - assertEquals(sourceSet, 101, + assertEquals(sourceSet, 107, pack.getAsJsonObject("pack").get("max_format").getAsInt()); JsonArray minimum = pack.getAsJsonObject("pack").getAsJsonArray("min_format"); - assertEquals(sourceSet, 101, minimum.get(0).getAsInt()); + assertEquals(sourceSet, 107, minimum.get(0).getAsInt()); assertEquals(sourceSet, 1, minimum.get(1).getAsInt()); assertFalse(sourceSet, new File(fixtureRoot, "data/c/tags/items").exists()); assertFalse(sourceSet, new File(fixtureRoot, "data/c/tags/fluids").exists()); @@ -559,6 +562,38 @@ public void integrationFixturesUseDataFormat101AndSingularDataDirectories() thro assertTrue(new File(oilRoot, "data/forge/tags/fluid/crude_oil.json").isFile()); } + @Test + public void nativeSulfurAndCinnabarRemainSeparateFromMineralogyMaterials() throws Exception { + assertTagValues(new File(ROOT, "data/c/tags/item/storage_blocks/sulfur.json"), + "mineralogy:sulfur_block"); + assertTagValues(new File(ROOT, "data/c/tags/block/storage_blocks/sulfur.json"), + "mineralogy:sulfur_block"); + assertTagValues(new File(ROOT, "data/c/tags/item/dusts/sulfur.json"), + "mineralogy:sulfur_dust"); + assertTagValues(new File(ROOT, "data/forge/tags/item/storage_blocks/sulfur.json"), + "#c:storage_blocks/sulfur"); + assertTagValues(new File(ROOT, "data/forge/tags/item/dusts/sulfur.json"), + "#c:dusts/sulfur"); + + JsonObject sulfurBlock = json(new File(ROOT, + "data/mineralogy/recipe/sulfur_block.json")); + assertEquals("mineralogy:sulfur_dust", + sulfurBlock.getAsJsonObject("key").get("x").getAsString()); + JsonObject sulfurDust = json(new File(ROOT, + "data/mineralogy/recipe/sulfur_dust.json")); + assertEquals("#c:storage_blocks/sulfur", + sulfurDust.getAsJsonArray("ingredients").get(0).getAsString()); + + File recipeDirectory = new File(ROOT, "data/mineralogy/recipe"); + File[] recipes = recipeDirectory.listFiles((dir, name) -> name.endsWith(".json")); + assertNotNull(recipes); + for (File recipe : recipes) { + String contents = new String(Files.readAllBytes(recipe.toPath()), StandardCharsets.UTF_8); + assertFalse(recipe.getName(), contents.contains("minecraft:sulfur")); + assertFalse(recipe.getName(), contents.contains("minecraft:cinnabar")); + } + } + @Test public void generatedRecipeAdvancementsDisableTelemetry() throws Exception { File mineralogyAdvancements = new File(ROOT, "data/mineralogy/advancement/recipes"); @@ -666,8 +701,8 @@ public void nativeSlabsAndCobblestoneOverridesUseStableConditionalTags() throws @Test public void oilAndBuildMetadataUseStableTargetIdentities() throws Exception { String properties = new String(Files.readAllBytes(new File("gradle.properties").toPath()), StandardCharsets.UTF_8); - assertTrue(properties.contains("mod_version=6.1.2.2601022")); - assertTrue(properties.contains("orespawn_curse_file_id=8809908")); + assertTrue(properties.contains("mod_version=6.1.2.2602002")); + assertTrue(properties.contains("orespawn_curse_file_id=8830635")); String build = new String(Files.readAllBytes(new File("build.gradle").toPath()), StandardCharsets.UTF_8); assertTrue(build.contains("runtimeOnly(orespawnCoordinate)")); assertTrue(build.contains("https://maven.moddev.zone/releases")); @@ -869,7 +904,13 @@ private static Set stringSet(JsonArray values) { private static void assertRecipeBookFields(String name, JsonObject recipe) { String type = recipe.get("type").getAsString(); if ("minecraft:crafting_shaped".equals(type)) { - assertTrue(name, recipe.has("category")); + Set categoryFreeRecipes = new HashSet(Arrays.asList( + "furnace.json", + "brewing_stand.json", + "coast_armor_trim_smithing_template.json", + "sentry_armor_trim_smithing_template.json", + "vex_armor_trim_smithing_template.json")); + assertEquals(name, !categoryFreeRecipes.contains(name), recipe.has("category")); assertTrue(name, recipe.has("show_notification")); assertTrue(name, recipe.get("show_notification").getAsBoolean()); } else if ("minecraft:crafting_shapeless".equals(type)) { diff --git a/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java b/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java index c0a8fd1e7..07a6e3e5f 100644 --- a/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java @@ -19,8 +19,8 @@ public void releaseMetadataIdentifiesTheGenericNeoForgeTarget() throws Exception try (FileInputStream input = new FileInputStream("gradle.properties")) { properties.load(input); } - assertEquals("6.1.2.2601022", properties.getProperty("mod_version")); - assertEquals("26.1.2", properties.getProperty("minecraft_version")); + assertEquals("6.1.2.2602002", properties.getProperty("mod_version")); + assertEquals("26.2", properties.getProperty("minecraft_version")); assertEquals(properties.getProperty("mc_version"), properties.getProperty("minecraft_version")); assertEquals("neoforge", properties.getProperty("loader_name")); assertEquals("2", properties.getProperty("loader_code")); @@ -29,10 +29,11 @@ public void releaseMetadataIdentifiesTheGenericNeoForgeTarget() throws Exception assertEquals("25", properties.getProperty("gradle_java_version")); assertEquals("240974", properties.getProperty("curseforge_project_id")); assertEquals("zone.moddev.mc.mineralogy", properties.getProperty("mod_group")); - assertEquals("4.0.16.2601022", properties.getProperty("orespawn_version")); - assertEquals("8809908", properties.getProperty("orespawn_curse_file_id")); - assertEquals("4F6612B89FC65E4860E962E8EA45CC03B752330060B3362112EBEBC7AA9C2E6C", + assertEquals("4.0.16.2602002", properties.getProperty("orespawn_version")); + assertEquals("8830635", properties.getProperty("orespawn_curse_file_id")); + assertEquals("16DFD59B5083BB1F7FE399091AC9778F9D10F397FE214865C937F00D1C20625A", properties.getProperty("orespawn_sha256")); + assertFalse(properties.containsKey("neogradle.subsystems.decompiler.enabled")); String wrapper = text("gradle/wrapper/gradle-wrapper.properties"); assertTrue(wrapper.contains("gradle-9.2.1-bin.zip")); } @@ -44,16 +45,20 @@ public void ciAndSecurityChecksUsePinnedTargetNativeBuilds() throws Exception { String wrapper = text(".github/workflows/validate-gradle-build.yml"); String staging = text("gradle/stage-orespawn-release.sh"); assertTrue(ci.contains("name: Build, test, and audit")); - assertTrue(ci.contains("master-26.1.2-neo")); + assertTrue(ci.contains("master-26.2-neo")); assertTrue(ci.contains("java-version: '25.0.3+9.0.LTS'")); assertTrue(ci.contains("Install exact Java 25")); assertTrue(ci.contains("Cold NeoForge bootstrap")); + assertFalse(ci.contains("./gradlew clean check")); + assertTrue(ci.contains("./gradlew clean \\")); + assertTrue(ci.contains("./gradlew check build javadoc")); assertTrue(ci.contains("verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums")); assertTrue(ci.contains("eclipse verifyEclipseProductionClasspath")); assertTrue(ci.contains("CHANGELOG.txt")); assertTrue(ci.contains("PorespawnVerificationRepository")); assertFalse(ci.contains("genEclipseRuns")); assertFalse(ci.contains("Mavenizer")); + assertFalse(ci.contains("neogradle.subsystems.decompiler.enabled=true")); assertFalse(ci.contains("JAVA_HOME_8_X64")); assertFalse(ci.contains("JAVA_HOME_25_X64")); assertTrue(staging.contains("https://www.curseforge.com/api/v1/mods/$project_id/files/$file_id/download")); @@ -87,9 +92,11 @@ public void buildPublishesOnlyThePreparedRemoteBundle() throws Exception { assertTrue(build.contains("reproducibleFileOrder = true")); assertTrue(build.contains("filesMatching('META-INF/neoforge.mods.toml')")); assertTrue(build.contains("from('docs')")); - assertTrue(build.contains("NeoForge 26.1 uses official names")); + assertTrue(build.contains("NeoForge 26.2 uses official names")); assertTrue(build.contains("'zone/moddev/mc/mineralogy/Mineralogy.class'")); - assertTrue(build.contains("928 NeoForge 26.1.2 item definitions")); + assertTrue(build.contains("928 NeoForge 26.2 item definitions")); + assertTrue(build.contains("task.name.startsWith('cacheVersionExecutable')")); + assertTrue(build.contains("NeoForge 26.2 must retain its validated binary userdev path")); assertTrue(build.contains("assets/mineralogy/items/")); assertTrue(build.contains("def preparedReleaseDir = project.findProperty('preparedReleaseDir')")); assertTrue(build.contains("tasks.register('verifyPreparedReleaseArtifacts')")); From 53393ccb8053722d23b9c32a0a8e42ce1b84d939 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Fri, 11 Sep 2026 16:11:33 +0100 Subject: [PATCH 2/2] Separate CodeQL clean and compile phases --- .github/workflows/codeql-analysis.yml | 6 +++--- .../zone/moddev/mc/mineralogy/WorkflowContractTest.java | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1109fd92f..e14e7cd3d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -40,14 +40,14 @@ jobs: run: | set -euo pipefail chmod +x ./gradlew - gradle_args=( - clean classes --no-daemon --stacktrace --max-workers=2 + gradle_jdk_args=( "-Dorg.gradle.java.installations.paths=$JAVA_HOME" -Dorg.gradle.java.installations.auto-detect=false -Dorg.gradle.java.installations.auto-download=false ) + ./gradlew clean --no-daemon --stacktrace --max-workers=2 "${gradle_jdk_args[@]}" for attempt in 1 2 3; do - if ./gradlew "${gradle_args[@]}"; then + if ./gradlew classes --no-daemon --stacktrace --max-workers=2 "${gradle_jdk_args[@]}"; then exit 0 fi if [ "$attempt" -eq 3 ]; then diff --git a/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java b/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java index 07a6e3e5f..83ceb2e46 100644 --- a/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java @@ -65,7 +65,9 @@ public void ciAndSecurityChecksUsePinnedTargetNativeBuilds() throws Exception { assertTrue(staging.contains("sha256sum")); assertTrue(codeql.contains("github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28")); assertTrue(codeql.contains("Install exact Java 25")); - assertTrue(codeql.contains("clean classes --no-daemon --stacktrace --max-workers=2")); + assertFalse(codeql.contains("clean classes")); + assertTrue(codeql.contains("./gradlew clean --no-daemon --stacktrace --max-workers=2")); + assertTrue(codeql.contains("./gradlew classes --no-daemon --stacktrace --max-workers=2")); assertFalse(codeql.contains("Mavenizer")); assertTrue(wrapper.contains("gradle/actions/wrapper-validation@9c971963bec38e04b3d30dcc455b5382be2fdbfb")); }