diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59e3e584d..4b082f4c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,19 +1,19 @@ -name: Mineralogy 1.21.11 NeoForge CI +name: Mineralogy 26.1.2 NeoForge CI on: push: branches: - - master-1.21.11-neo + - master-26.1.2-neo - 'feature/**' pull_request: branches: - - master-1.21.11-neo + - master-26.1.2-neo permissions: contents: read concurrency: - group: mineralogy-1.21.11-neo-${{ github.workflow }}-${{ github.ref }} + group: mineralogy-26.1.2-neo-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -24,11 +24,11 @@ jobs: steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - - name: Install exact Java 21 + - name: Install exact Java 25 uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin - java-version: '21.0.7+6.0.LTS' + java-version: '25.0.3+9.0.LTS' - name: Bootstrap an isolated empty NeoGradle cache shell: bash run: | @@ -52,11 +52,11 @@ jobs: steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - - name: Install exact Java 21 + - name: Install exact Java 25 uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin - java-version: '21.0.7+6.0.LTS' + java-version: '25.0.3+9.0.LTS' - name: Set up Gradle uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6 - name: Stage exact OreSpawn release dependency @@ -91,20 +91,20 @@ jobs: - name: Upload audited release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: Mineralogy-1.21.11-neoforge-${{ github.sha }} + name: Mineralogy-26.1.2-neoforge-${{ github.sha }} if-no-files-found: error retention-days: 30 path: | - build/libs/Mineralogy-6.1.2.121112.jar - build/libs/Mineralogy-6.1.2.121112-sources.jar - build/libs/Mineralogy-6.1.2.121112-javadoc.jar + 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/release/SHA256SUMS CHANGELOG.txt - name: Upload diagnostics on failure if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: Mineralogy-1.21.11-neoforge-diagnostics-${{ github.sha }} + name: Mineralogy-26.1.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 5b976aaa5..e331c11a9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -3,11 +3,11 @@ name: CodeQL on: push: branches: - - master-1.21.11-neo + - master-26.1.2-neo - 'feature/**' pull_request: branches: - - master-1.21.11-neo + - master-26.1.2-neo schedule: - cron: '43 7 * * 4' @@ -24,11 +24,11 @@ jobs: steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - - name: Install exact Java 21 + - name: Install exact Java 25 uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin - java-version: '21.0.7+6.0.LTS' + java-version: '25.0.3+9.0.LTS' - name: Set up Gradle uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6 - name: Initialize CodeQL diff --git a/.github/workflows/validate-gradle-build.yml b/.github/workflows/validate-gradle-build.yml index 0d91b4d05..4e4880adb 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-1.21.11-neo + - master-26.1.2-neo - 'feature/**' pull_request: branches: - - master-1.21.11-neo + - master-26.1.2-neo permissions: contents: read diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b4a470e53..01da69c8d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,31 @@ +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 + NeoForge 26.1.2.94 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. +- Adapted loot tools to Minecraft 26.1's `ItemInstance`, fertilizer helper + stacks to post-registration construction, rock-furnace crafting remainders + to `ItemStackTemplate`, and furnace recipe assembly to the target signature. + Existing furnace contents, fuel, burn/cook progress, and state synchronization + remain intact. +- Registered crude-oil rendering through NeoForge 26.1's native fluid-model + event and retained the accepted native texture synchronization for andesite, + diorite, granite, basalt, and tuff. +- Retargeted the legacy conversion Mixins to the four-argument chunk upgrader, + moved tag rebinding to the target reload hook, and indexed both legacy root + region files and Minecraft 26.1's Overworld dimension-region layout. All + 18,192 mappings, selected-world restoration, sidecars, protected chunks, and + legacy furnace normalization remain intact. +- Regenerated and audited the existing 1,433 recipe/advancement pairs for the + target codecs without obsolete stonecutting groups. The 18 slab bridges, 48 + Minecraft recipe overrides, 21 advancement overrides, 19 configurable + cobblestone routes, tuff matrix, and stone-spear compatibility are unchanged. +- Updated metadata, CI, documentation, release checks, and the exact dependency + pin for Minecraft 26.1.2, NeoForge 26.1.2.94, OreSpawn 4.0.16.2601022, + Java 25, resource format 84, and data format 101.1. Mineralogy still + registers no world generator. + Mineralogy 6.1.2.121112 for Minecraft 1.21.11 NeoForge - Ported the accepted NeoForge 1.21.1 product to Minecraft 1.21.11 and diff --git a/README.md b/README.md index 18ddd8866..bbb54f31f 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-1.21.11-neo)](https://github.com/MinecraftModDevelopmentMods/MinecraftMineralogy/actions/workflows/ci.yml?query=branch%3Amaster-1.21.11-neo) +[![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) -# Mineralogy 6 for Minecraft 1.21.11 +# Mineralogy 6 for Minecraft 26.1.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.121112` for NeoForge `21.11.45` and is built -and tested against OreSpawn `4.0.16.121112`. Its declared compatibility range is +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 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 1.21.11 branch; use the jar that matches the loader in your modpack. +Forge 26.1.2 branch; use the jar that matches the loader in your modpack. ## Configuration and help diff --git a/build.gradle b/build.gradle index a5b505691..3c906612d 100644 --- a/build.gradle +++ b/build.gradle @@ -44,13 +44,13 @@ 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] != '121112') { - throw new GradleException("Mineralogy 1.21.11 NeoForge releases must use target 121112: ${project.mod_version}") +if (versionParts[3] != '2601022') { + throw new GradleException("Mineralogy 26.1.2 NeoForge releases must use target 2601022: ${project.mod_version}") } java { toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) vendor = JvmVendorSpec.ADOPTIUM } withSourcesJar() @@ -64,11 +64,11 @@ tasks.named('sourcesJar', Jar) { tasks.withType(JavaCompile).configureEach { javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) vendor = JvmVendorSpec.ADOPTIUM } - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 options.encoding = 'UTF-8' options.compilerArgs.addAll(['-Xlint:deprecation', '-Xmaxerrs', '1000']) } @@ -191,7 +191,7 @@ configurations { dependencies { implementation "net.neoforged:neoforge:${project.neo_version}" - // NeoForge 21.11 uses official names in both development and production, so the + // NeoForge 26.1 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 } @@ -258,7 +258,7 @@ tasks.named('jar', Jar) { 'Implementation-Title' : 'Mineralogy', 'Implementation-Version': project.version, 'Implementation-Vendor' : 'SkyBlade1978', - 'Built-On-Java' : '21', + 'Built-On-Java' : '25', 'Mineralogy-Loader' : 'neoforge', 'MixinConfigs' : 'mineralogy.mixins.json', 'Built-On' : "${project.minecraft_version}-${project.neo_version}" @@ -276,11 +276,11 @@ tasks.register('compileOilCompatibilityFixture', JavaCompile) { classpath = files(sourceSets.main.output, sourceSets.main.compileClasspath) destinationDirectory = oilCompatibilityClasses javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) vendor = JvmVendorSpec.ADOPTIUM } options.encoding = 'UTF-8' - options.release = 21 + options.release = 25 } tasks.register('oilCompatibilityFixtureJar', Jar) { dependsOn tasks.named('compileOilCompatibilityFixture') @@ -301,11 +301,11 @@ tasks.register('compileRecipeIntegrationFixture', JavaCompile) { classpath = files(sourceSets.main.output, sourceSets.main.compileClasspath) destinationDirectory = recipeIntegrationClasses javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) vendor = JvmVendorSpec.ADOPTIUM } options.encoding = 'UTF-8' - options.release = 21 + options.release = 25 } tasks.register('recipeIntegrationFixtureJar', Jar) { dependsOn tasks.named('compileRecipeIntegrationFixture') @@ -323,7 +323,7 @@ tasks.register('runRegionPaletteAudit', JavaExec) { classpath = files(recipeIntegrationClasses, sourceSets.main.runtimeClasspath) mainClass = 'zone.moddev.mc.mineralogy.recipeprobe.RegionPaletteAudit' javaLauncher = javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) vendor = JvmVendorSpec.ADOPTIUM } doFirst { @@ -460,13 +460,13 @@ tasks.register('verifyMavenCoordinates') { tasks.register('verifyReleaseConfiguration') { group = 'verification' - description = 'Verifies the exact Mineralogy 1.21.11 NeoForge release identity.' + description = 'Verifies the exact Mineralogy 26.1.2 NeoForge release identity.' doLast { - if (project.mod_version != '6.1.2.121112' + if (project.mod_version != '6.1.2.2601022' || project.mod_group != expectedMavenGroup - || project.minecraft_version != '1.21.11' - || project.neo_version != '21.11.45') { - throw new GradleException('Unexpected Mineralogy 1.21.11 NeoForge release identity') + || project.minecraft_version != '26.1.2' + || project.neo_version != '26.1.2.94') { + throw new GradleException('Unexpected Mineralogy 26.1.2 NeoForge release identity') } } } @@ -475,20 +475,20 @@ tasks.register('verifyReleaseDependencies') { group = 'verification' description = 'Resolves and verifies the exact released OreSpawn dependency.' doLast { - if (project.mod_version != '6.1.2.121112' + if (project.mod_version != '6.1.2.2601022' || project.minecraft_version != project.mc_version - || project.mc_version != '1.21.11' + || project.mc_version != '26.1.2' || project.loader_name != 'neoforge' || project.loader_code != '2' - || project.java_version != '21' - || project.java_toolchain_version != '21.0.7+6' - || project.gradle_java_version != '21' + || project.java_version != '25' + || project.java_toolchain_version != '25.0.3+9' + || project.gradle_java_version != '25' || project.curseforge_project_id != '240974') { throw new GradleException('Unexpected generic release dispatcher metadata') } - if (project.orespawn_version != '4.0.16.121112' || + if (project.orespawn_version != '4.0.16.2601022' || project.orespawn_curse_project_id != '245586' || - project.orespawn_curse_file_id != '8809764') { + project.orespawn_curse_file_id != '8809908') { throw new GradleException('Unexpected OreSpawn release coordinates') } File artifact = configurations.orespawnRelease.resolvedConfiguration.resolvedArtifacts @@ -616,7 +616,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 21.11 item definitions') + throw new GradleException('Release jar must contain 1,144 legacy item models and 928 NeoForge 26.1.2 item definitions') } itemDefinitions.each { definitionName -> String id = definitionName.substring( @@ -627,7 +627,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 21.11 item definition: ${definitionName}") + throw new GradleException("Invalid NeoForge 26.1.2 item definition: ${definitionName}") } } def blockModelText = names.findAll { @@ -687,7 +687,7 @@ tasks.register('verifyReleaseArtifacts') { throw new GradleException("Invalid class header in ${entry.name}") } int major = ((header[6] & 0xff) << 8) | (header[7] & 0xff) - if (major != 65) throw new GradleException("${entry.name} is class version ${major}, expected Java 21 (65)") + if (major != 69) throw new GradleException("${entry.name} is class version ${major}, expected Java 25 (69)") } finally { stream.close() @@ -702,7 +702,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 1.21.11 world heights') + throw new GradleException('Packaged provider does not use Minecraft 26.1.2 world heights') } if (provider.rocks['mineralogy:rock/minecraft/basalt']?.block != 'minecraft:basalt' || provider.rocks['mineralogy:rock/minecraft/tuff']?.block != 'minecraft:tuff' || @@ -719,7 +719,7 @@ tasks.register('verifyReleaseArtifacts') { dimension?.host_blocks == ['minecraft:stone', 'minecraft:deepslate'] && dimension?.host_tags == [] }) { - throw new GradleException('Packaged provider does not use the Minecraft 1.21.11 native-rock and deepslate contract') + throw new GradleException('Packaged provider does not use the Minecraft 26.1.2 native-rock and deepslate contract') } byte[] providerBytes = zip.getInputStream( zip.getEntry('data/mineralogy/orespawn/provider.json')).bytes @@ -741,7 +741,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 1.21.11 item-stack id field') + throw new GradleException('Custom advancement icon must use the Minecraft 26.1.2 item-stack id field') } def verifyAdvancementPredicates = { advancement, String source -> advancement.criteria?.each { criterionName, criterion -> @@ -754,7 +754,7 @@ tasks.register('verifyReleaseArtifacts') { ? holderSet.isEmpty() || holderSet.any { !(it instanceof String) || it.isEmpty() } : !(holderSet instanceof String) || holderSet.isEmpty() }) { - throw new GradleException("Invalid Minecraft 1.21.11 item predicate in ${source}: ${criterionName}") + throw new GradleException("Invalid Minecraft 26.1.2 item predicate in ${source}: ${criterionName}") } } } @@ -765,7 +765,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 1.21.11 recipe advancement must disable telemetry: ${entryName}") + throw new GradleException("Minecraft 26.1.2 recipe advancement must disable telemetry: ${entryName}") } if (advancement.criteria != null) verifyAdvancementPredicates(advancement, entryName) } @@ -861,10 +861,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 1.21.11 stonecutting result: ${recipe}") + throw new GradleException("Invalid Minecraft 26.1.2 stonecutting result: ${recipe}") } } else if (data.result?.id == null) { - throw new GradleException("Invalid Minecraft 1.21.11 slab result: ${recipe}") + throw new GradleException("Invalid Minecraft 26.1.2 slab result: ${recipe}") } } def families = ['andesite', 'basalt', 'diorite', 'granite', 'rhyolite', @@ -938,7 +938,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 21.11 wall blockstates and tall-side models") + throw new GradleException("Release jar must contain all 108 NeoForge 26.1.2 wall blockstates and tall-side models") } } finally { diff --git a/docs/CONTENT_CONFIG.md b/docs/CONTENT_CONFIG.md index f3a0b4ab7..4969e0c98 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 1.21.11 +unconditional cobblestone equivalents in tag-backed recipes. The three 26.1.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 b059eb0fb..5b8717fc1 100644 --- a/docs/DEVELOPER_GUIDE.md +++ b/docs/DEVELOPER_GUIDE.md @@ -40,14 +40,15 @@ 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 1.21.11's `minecraft:stone_crafting_materials` and +Minecraft 26.1.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 1.21.11 removed the old mutable ingredient caches, so +mods' members. Minecraft 26.1.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 the recipe manager observe the new membership immediately. @@ -61,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 1.21.11 retains three additional configurable recipes: coast, sentry, and vex +Minecraft 26.1.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 1.21.11 also owns andesite, basalt, diorite, granite, tuff, and several +Minecraft 26.1.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 @@ -123,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 1.21.11 JSON under +All Mineralogy recipes are native Minecraft/NeoForge 26.1.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 @@ -133,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 -1.21.11's advancement requirements matrix to require the matching source plus +26.1.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 @@ -160,24 +161,29 @@ 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 21.11 converts pre-flattening chunks lazily. Required Mixins expand +NeoForge 26.1 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. -The obsolete JavaScript coremod is deliberately absent. Validate both previously +Minecraft 26.1'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 unloaded occupied furnaces and new chunks at an old-world boundary in the 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 21, -with an exact Java 21 toolchain for production and test bytecode: +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: ```powershell -$env:JAVA_HOME='path-to-a-Java-21-jdk' +$env:JAVA_HOME='path-to-Temurin-25.0.3+9' $env:GRADLE_USER_HOME='D:\MinecraftMineralogy\.gradle-verify-cache' .\gradlew.bat clean check build javadoc verifyReleaseConfiguration verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums --no-daemon .\gradlew.bat eclipse verifyEclipseProductionClasspath --no-daemon @@ -189,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 `121112` -for Minecraft 1.21.11 NeoForge and does not append CI build numbers. +[Mineralogy Versioning](VERSIONS.md). This branch validates target `2601022` +for Minecraft 26.1.2 NeoForge and does not append CI build numbers. diff --git a/docs/PLAYER_GUIDE.md b/docs/PLAYER_GUIDE.md index 1b9ad94ca..1e28e15f2 100644 --- a/docs/PLAYER_GUIDE.md +++ b/docs/PLAYER_GUIDE.md @@ -2,8 +2,8 @@ ## Installing -Mineralogy 6 needs Minecraft 1.21.11, NeoForge 21.11.45, and OreSpawn -4.0.16.121112. Do not mix this NeoForge jar with the separate Forge build. +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. 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 1.21.11 start, Mineralogy recognizes the old saved registry and +On the first 26.1.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 1.21.11 accepts Y `-64` through `319`; Depth Spread accepts `1` through +Minecraft 26.1.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 1.21.11 graphical editor. Stop +The terrain-host list is not exposed by OreSpawn's 26.1.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 1.21.11 these resolve through target-native block tags. Exact +Minecraft 26.1.2 these resolve through target-native block tags. Exact `host_blocks` entries are the clearest choice for one modded stone. -Minecraft 1.21.11 matches a `host_blocks` entry by flattened block registry +Minecraft 26.1.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 1.21.11 uses the dimension +separate Mineralogy dimension option. Minecraft 26.1.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 1.21.11 graphical editor does not expose terrain-dimension or rock-membership +The 26.1.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 e6adb97ea..18aeb8f48 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 1.21.11 heights `-64` through `319` and Overworld-only terrain defaults. +- Minecraft 26.1.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 1.21.11 uses the registered dimension-type ID, such as +Minecraft 26.1.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 1.21.11 editor does not expose terrain-dimension or rock-membership fields, so +The 26.1.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 1.21.11, terrain hosts are baked as flattened block identities. +On Minecraft 26.1.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 5317171f5..9acb08762 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Mineralogy Guide -Mineralogy 6 for Minecraft 1.21.11 supplies rock, mineral, construction, and +Mineralogy 6 for Minecraft 26.1.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 2a1dbd041..c5c2c4811 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 1.21.11 NeoForge release is therefore: +this Minecraft 26.1.2 NeoForge release is therefore: ```text -6.1.2.121112 +6.1.2.2601022 ``` 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.121112`, not `1.21.11-6.1.2.121112`. The Target already makes tags unique +`6.1.2.2601022`, not `26.1.2-6.1.2.2601022`. The Target already makes tags unique across Minecraft versions and loaders. ## Reading the target component @@ -61,10 +61,12 @@ minor digits, and all remaining digits for the Minecraft major version. | 1.21.1 | NeoForge | `121012` | `6.1.2.121012` | | 1.21.11 | Forge | `121111` | `6.1.2.121111` | | 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` | -The 1.21.11 NeoForge row records this branch's current release. The other rows illustrate +The 26.1.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. @@ -128,6 +130,7 @@ Minecraft 1.20.1 / Forge / Mineralogy 6.1.2.120011 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 and loader APIs may require different internal code without changing @@ -159,8 +162,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 1.21.11 NeoForge release used for -this candidate is `4.0.16.121112`. The dependency range deliberately describes the supported +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 functional OreSpawn generation; NeoForge still prevents jars for another Minecraft target from loading together. @@ -173,7 +176,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.121112`. +branch, published metadata and artifacts therefore use `6.1.2.2601022`. Every release note should state: diff --git a/gradle.properties b/gradle.properties index 43793ae41..9433b728a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ org.gradle.caching=true org.gradle.parallel=false neogradle.subsystems.decompiler.enabled=true -mod_version=6.1.2.121112 +mod_version=6.1.2.2601022 mod_group=zone.moddev.mc.mineralogy mod_group_id=zone.moddev.mc.mineralogy mod_id=mineralogy @@ -17,20 +17,20 @@ mod_authors=Cyanobacterium, SkyBlade1978, JRIwanek mod_description=Fills the world with real-world rocks. # Release metadata consumed by the generic dispatcher. -minecraft_version=1.21.11 -mc_version=1.21.11 -minecraft_version_range=[1.21.11] +minecraft_version=26.1.2 +mc_version=26.1.2 +minecraft_version_range=[26.1.2] loader_name=neoforge loader_code=2 -neo_version=21.11.45 -neo_version_range=[21.11.45,21.12) -java_version=21 -java_toolchain_version=21.0.7+6 -java_setup_version=21.0.7+6.0.LTS -gradle_java_version=21 +neo_version=26.1.2.94 +neo_version_range=[26.1.2.94,26.1.3) +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.121112 +orespawn_version=4.0.16.2601022 orespawn_curse_project_id=245586 -orespawn_curse_file_id=8809764 -orespawn_sha256=F7F2840D11090EC3B6A7A73AD380CFCAC3C034D3C8FCD9914CA1AAD4219E19E9 +orespawn_curse_file_id=8809908 +orespawn_sha256=4F6612B89FC65E4860E962E8EA45CC03B752330060B3362112EBEBC7AA9C2E6C diff --git a/resourcepack/x128/pack.mcmeta b/resourcepack/x128/pack.mcmeta index 03cdd6175..ce750e87a 100644 --- a/resourcepack/x128/pack.mcmeta +++ b/resourcepack/x128/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 75, - "min_format": 75, + "max_format": 84, + "min_format": 84, "description": "Minecraft Mineralogy\n-FoxNekitsune & DrCyano" } } diff --git a/resourcepack/x16/pack.mcmeta b/resourcepack/x16/pack.mcmeta index 03cdd6175..ce750e87a 100644 --- a/resourcepack/x16/pack.mcmeta +++ b/resourcepack/x16/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 75, - "min_format": 75, + "max_format": 84, + "min_format": 84, "description": "Minecraft Mineralogy\n-FoxNekitsune & DrCyano" } } diff --git a/resourcepack/x32/pack.mcmeta b/resourcepack/x32/pack.mcmeta index 8bc4db74d..a3293412d 100644 --- a/resourcepack/x32/pack.mcmeta +++ b/resourcepack/x32/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 75, - "min_format": 75, + "max_format": 84, + "min_format": 84, "description": "Minecraft Mineralogy\n-Fox Nekitsune & DrCyano" } } diff --git a/resourcepack/x64/pack.mcmeta b/resourcepack/x64/pack.mcmeta index 8bc4db74d..a3293412d 100644 --- a/resourcepack/x64/pack.mcmeta +++ b/resourcepack/x64/pack.mcmeta @@ -1,7 +1,7 @@ { "pack": { - "max_format": 75, - "min_format": 75, + "max_format": 84, + "min_format": 84, "description": "Minecraft Mineralogy\n-Fox Nekitsune & DrCyano" } } diff --git a/scripts/generate-locales.ps1 b/scripts/generate-locales.ps1 index aa451787d..e7bbb4960 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 1.21.11 JSON locales with 938 ordered keys each.' +Write-Output 'Generated 17 reviewed Mineralogy 26.1.2 JSON locales with 938 ordered keys each.' diff --git a/scripts/generate-recipes.ps1 b/scripts/generate-recipes.ps1 index 152ae208c..ed2022029 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 1.21.11. Mineralogy keeps its +# Minecraft owns these full-block identities in 26.1.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 1.21.11 advancement predicate" + throw "Cannot convert recipe ingredient into a Minecraft 26.1.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 1.21.11 tag mapping for legacy OreDictionary key $ore" + throw "No Minecraft 26.1.2 tag mapping for legacy OreDictionary key $ore" } function Convert-CamelToSnake([string] $value) { @@ -1381,4 +1381,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 1.21.11 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.1.2 recipe advancements." diff --git a/src/main/java/zone/moddev/mc/mineralogy/blocks/Ore.java b/src/main/java/zone/moddev/mc/mineralogy/blocks/Ore.java index 816f2d9c9..933480915 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/blocks/Ore.java +++ b/src/main/java/zone/moddev/mc/mineralogy/blocks/Ore.java @@ -48,6 +48,6 @@ public ItemLike getItemDropped() { @Override public List getDrops(BlockState state, Builder builder) { return Collections.singletonList(new ItemStack(getItemDropped(), - builder.getLevel().random.nextInt(dropRange) + dropAdduct)); + builder.getLevel().getRandom().nextInt(dropRange) + dropAdduct)); } } diff --git a/src/main/java/zone/moddev/mc/mineralogy/blocks/Rock.java b/src/main/java/zone/moddev/mc/mineralogy/blocks/Rock.java index 2a51a3588..9a10a081b 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/blocks/Rock.java +++ b/src/main/java/zone/moddev/mc/mineralogy/blocks/Rock.java @@ -15,6 +15,7 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemInstance; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.storage.loot.LootParams.Builder; @@ -55,15 +56,21 @@ public List getDrops(BlockState state, Builder builder) { } protected static boolean hasSilkTouch(Builder builder) { - ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); - return tool != null && !tool.isEmpty() + ItemInstance toolInstance = builder.getOptionalParameter(LootContextParams.TOOL); + if (!(toolInstance instanceof ItemStack tool)) { + return false; + } + return !tool.isEmpty() && EnchantmentHelper.getItemEnchantmentLevel( builder.getLevel().registryAccess().getOrThrow(Enchantments.SILK_TOUCH), tool) > 0; } protected static int getFortuneLevel(Builder builder) { - ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL); - return tool == null || tool.isEmpty() ? 0 : EnchantmentHelper.getItemEnchantmentLevel( + ItemInstance toolInstance = builder.getOptionalParameter(LootContextParams.TOOL); + if (!(toolInstance instanceof ItemStack tool) || tool.isEmpty()) { + return 0; + } + return EnchantmentHelper.getItemEnchantmentLevel( builder.getLevel().registryAccess().getOrThrow(Enchantments.FORTUNE), tool); } } diff --git a/src/main/java/zone/moddev/mc/mineralogy/client/ClientSetup.java b/src/main/java/zone/moddev/mc/mineralogy/client/ClientSetup.java index 20da3d0ff..97503d4c7 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/client/ClientSetup.java +++ b/src/main/java/zone/moddev/mc/mineralogy/client/ClientSetup.java @@ -3,40 +3,31 @@ import zone.moddev.mc.mineralogy.Mineralogy; import zone.moddev.mc.mineralogy.init.MineralogyFluids; -import net.minecraft.client.renderer.chunk.ChunkSectionLayer; -import net.minecraft.client.renderer.ItemBlockRenderTypes; -import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; -import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent; +import net.minecraft.client.renderer.block.FluidModel; +import net.minecraft.client.resources.model.sprite.Material; +import net.minecraft.resources.Identifier; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; +import net.neoforged.neoforge.client.event.RegisterFluidModelsEvent; @EventBusSubscriber(modid = Mineralogy.MODID, value = Dist.CLIENT) public final class ClientSetup { - private ClientSetup() { - } + private static final Identifier CRUDE_OIL_STILL = + Identifier.fromNamespaceAndPath(Mineralogy.MODID, "blocks/crude_oil_still"); + private static final Identifier CRUDE_OIL_FLOW = + Identifier.fromNamespaceAndPath(Mineralogy.MODID, "blocks/crude_oil_flow"); - @SubscribeEvent - public static void clientSetup(FMLClientSetupEvent event) { - // Block render types are declared by their model JSON on NeoForge 21.1. - // Fluid render layers still use the target-native client registration API. - ItemBlockRenderTypes.setRenderLayer(MineralogyFluids.CRUDE_OIL.get(), ChunkSectionLayer.TRANSLUCENT); - ItemBlockRenderTypes.setRenderLayer(MineralogyFluids.FLOWING_CRUDE_OIL.get(), ChunkSectionLayer.TRANSLUCENT); + private ClientSetup() { } @SubscribeEvent - public static void registerClientExtensions(RegisterClientExtensionsEvent event) { - event.registerFluidType(new IClientFluidTypeExtensions() { - @Override - public net.minecraft.resources.Identifier getStillTexture() { - return MineralogyFluids.crudeOilStillTexture(); - } - - @Override - public net.minecraft.resources.Identifier getFlowingTexture() { - return MineralogyFluids.crudeOilFlowTexture(); - } - }, MineralogyFluids.CRUDE_OIL_TYPE.get()); + public static void registerFluidModels(RegisterFluidModelsEvent event) { + FluidModel.Unbaked model = new FluidModel.Unbaked( + new Material(CRUDE_OIL_STILL, true), + new Material(CRUDE_OIL_FLOW, true), + null, + null); + event.register(model, MineralogyFluids.CRUDE_OIL, MineralogyFluids.FLOWING_CRUDE_OIL); } } 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 ebc304546..2dc066a89 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 21.11 tags. */ +/** Applies the legacy cobblestone option to NeoForge 26.1 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 21.11 cobblestone policy: enabled={}, rocks={}, " + Mineralogy.LOGGER.debug("Applied NeoForge 26.1 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 2806ee821..27766c5d9 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 1.21.11 constructs an + * Applies the stable registry identity before Minecraft 26.1.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 e4fec5846..187c09ca6 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java +++ b/src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java @@ -13,8 +13,6 @@ import net.minecraft.world.level.Level; public class MineralFertilizer extends Item { - private final ItemStack phantomBonemeal = new ItemStack(Items.BONE_MEAL, 27); - public MineralFertilizer() { super(RegistrationProperties.item(new Item.Properties(), "mineral_fertilizer")); } @@ -27,7 +25,9 @@ public InteractionResult useOn(UseOnContext context) { boolean canUse = BoneMealItem.applyBonemeal(context.getItemInHand(), world, target, player); if (canUse) { - phantomBonemeal.setCount(27); + // Minecraft 26.1 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++) { for (int dy = -2; dy <= 2; dy++) { for (int dz = -1; dz <= 1; dz++) { 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 cfc471f6a..3b8e8fe77 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 1.21.11 throws when a block tag is queried before the first tag + * Minecraft 26.1.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 48369abe5..9e7149834 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java +++ b/src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java @@ -8,13 +8,12 @@ import zone.moddev.mc.mineralogy.compat.CobblestoneTagPolicy; /** - * NeoForge 21.11 leaves the server-side TagsUpdatedEvent call disabled. Rebind the - * affected named sets immediately after vanilla commits the pending tag load, - * which also covers every later /reload. + * Rebind the affected named sets immediately after Minecraft 26.1.2 commits + * pending tags and static components, which also covers every later /reload. */ @Mixin(ReloadableServerResources.class) public abstract class ReloadableServerResourcesMixin { - @Inject(method = "updateStaticRegistryTags", at = @At("TAIL")) + @Inject(method = "updateComponentsAndStaticRegistryTags", at = @At("TAIL")) private void mineralogy$rebindCobblestoneTags(CallbackInfo callback) { ReloadableServerResources resources = (ReloadableServerResources) (Object) this; CobblestoneTagPolicy.apply(resources.fullRegistries().lookup()); diff --git a/src/main/java/zone/moddev/mc/mineralogy/mixin/SimpleRegionStorageMixin.java b/src/main/java/zone/moddev/mc/mineralogy/mixin/SimpleRegionStorageMixin.java index a532c1bc6..3fd7c6405 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/mixin/SimpleRegionStorageMixin.java +++ b/src/main/java/zone/moddev/mc/mineralogy/mixin/SimpleRegionStorageMixin.java @@ -13,18 +13,20 @@ @Mixin(SimpleRegionStorage.class) abstract class SimpleRegionStorageMixin { @Inject( - method = "upgradeChunkTag(Lnet/minecraft/nbt/CompoundTag;ILnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;", + method = "upgradeChunkTag(Lnet/minecraft/nbt/CompoundTag;ILnet/minecraft/nbt/CompoundTag;I)Lnet/minecraft/nbt/CompoundTag;", at = @At("HEAD")) private void mineralogy$prepareLegacyChunk(CompoundTag chunk, int fallbackDataVersion, - @Nullable CompoundTag context, CallbackInfoReturnable callback) { + @Nullable CompoundTag context, int targetDataVersion, + CallbackInfoReturnable callback) { LegacyWorldDataHook.prepareLegacyChunk(chunk); } @Inject( - method = "upgradeChunkTag(Lnet/minecraft/nbt/CompoundTag;ILnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;", + method = "upgradeChunkTag(Lnet/minecraft/nbt/CompoundTag;ILnet/minecraft/nbt/CompoundTag;I)Lnet/minecraft/nbt/CompoundTag;", at = @At("RETURN"), cancellable = true) private void mineralogy$finalizeLegacyChunk(CompoundTag chunk, int fallbackDataVersion, - @Nullable CompoundTag context, CallbackInfoReturnable callback) { + @Nullable CompoundTag context, int targetDataVersion, + CallbackInfoReturnable callback) { callback.setReturnValue(LegacyWorldDataHook.finalizeLegacyChunk(callback.getReturnValue())); } } diff --git a/src/main/java/zone/moddev/mc/mineralogy/patching/LegacyWorldDataHook.java b/src/main/java/zone/moddev/mc/mineralogy/patching/LegacyWorldDataHook.java index 1ffd5fb3d..6905de683 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/patching/LegacyWorldDataHook.java +++ b/src/main/java/zone/moddev/mc/mineralogy/patching/LegacyWorldDataHook.java @@ -160,11 +160,17 @@ private static void install(File worldDirectory, CompoundTag blockSnapshot) { /** Reads only Anvil location tables so old chunks are protected before their NBT is loaded. */ private static int indexLegacyChunks(File worldDirectory) { - File regionDirectory = new File(worldDirectory, "region"); + indexLegacyRegionDirectory(new File(worldDirectory, "region")); + indexLegacyRegionDirectory(new File(worldDirectory, + "dimensions/minecraft/overworld/region")); + return LEGACY_MINERALOGY_CHUNKS.size(); + } + + private static void indexLegacyRegionDirectory(File regionDirectory) { File[] regionFiles = regionDirectory.listFiles((directory, name) -> (name.endsWith(".mca") || name.endsWith(".mcr")) && name.startsWith("r.")); if (regionFiles == null) { - return 0; + return; } byte[] locations = new byte[4096]; @@ -204,7 +210,6 @@ private static int indexLegacyChunks(File worldDirectory) { LOGGER.warn("Could not inspect legacy chunk locations in '{}'", regionFile, e); } } - return LEGACY_MINERALOGY_CHUNKS.size(); } private static void writeSidecar(File worldDirectory, CompoundTag blockSnapshot) { diff --git a/src/main/java/zone/moddev/mc/mineralogy/tileentity/TileEntityRockFurnace.java b/src/main/java/zone/moddev/mc/mineralogy/tileentity/TileEntityRockFurnace.java index 195d7f7ec..1f9083462 100644 --- a/src/main/java/zone/moddev/mc/mineralogy/tileentity/TileEntityRockFurnace.java +++ b/src/main/java/zone/moddev/mc/mineralogy/tileentity/TileEntityRockFurnace.java @@ -35,6 +35,7 @@ import net.minecraft.world.inventory.StackedContentsCompatible; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStackTemplate; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; @@ -214,9 +215,9 @@ private void tickServer(Level level, BlockPos pos) { if (isBurning()) { dirty = true; - ItemStack container = fuel.getCraftingRemainder(); - if (!container.isEmpty()) { - furnaceItemStacks.set(1, container); + ItemStackTemplate remainder = fuel.getCraftingRemainder(); + if (remainder != null) { + furnaceItemStacks.set(1, remainder.create()); } else if (!fuel.isEmpty()) { fuel.shrink(1); if (fuel.isEmpty()) { @@ -271,8 +272,7 @@ private boolean canSmelt(@Nullable RecipeHolder recipe) { if (level == null) { return false; } - ItemStack result = recipe.value().assemble(new SingleRecipeInput(furnaceItemStacks.get(0)), - level.registryAccess()); + ItemStack result = recipe.value().assemble(new SingleRecipeInput(furnaceItemStacks.get(0))); if (result.isEmpty()) { return false; } @@ -298,7 +298,7 @@ private void smeltItem(@Nullable RecipeHolder recipe) { } ItemStack input = furnaceItemStacks.get(0); - ItemStack result = recipe.value().assemble(new SingleRecipeInput(input), level.registryAccess()); + ItemStack result = recipe.value().assemble(new SingleRecipeInput(input)); ItemStack output = furnaceItemStacks.get(2); if (output.isEmpty()) { diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index a3162bbde..e0323d180 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,4 +1,4 @@ -# Minecraft 1.21.11 ingredients retain live HolderSet references. Expose only +# Minecraft 26.1.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/pack.mcmeta b/src/main/resources/pack.mcmeta index 19a9303d6..6b3c09d3d 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,9 +1,9 @@ { "pack": { "description": "mineralogy resources", - "max_format": 94, + "max_format": 101, "min_format": [ - 94, + 101, 1 ] } diff --git a/src/oilCompatibilityTest/resources/META-INF/neoforge.mods.toml b/src/oilCompatibilityTest/resources/META-INF/neoforge.mods.toml index 17233d5ba..b593df62a 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="[21.11.45,21.12)" +versionRange="[26.1.2.94,26.1.3)" ordering="NONE" side="BOTH" [[dependencies.poweradvantage]] modId="mineralogy" type="required" -versionRange="[6.1.2.121112]" +versionRange="[6.1.2.2601022]" ordering="AFTER" side="BOTH" diff --git a/src/oilCompatibilityTest/resources/pack.mcmeta b/src/oilCompatibilityTest/resources/pack.mcmeta index 5dd2ba7b0..228f5b815 100644 --- a/src/oilCompatibilityTest/resources/pack.mcmeta +++ b/src/oilCompatibilityTest/resources/pack.mcmeta @@ -1,6 +1,7 @@ { "pack": { "description": "Mineralogy historical oil compatibility fixture", - "pack_format": 34 + "max_format": 101, + "min_format": [101, 1] } } diff --git a/src/recipeIntegrationTest/java/zone/moddev/mc/mineralogy/fixture/RecipeIntegrationProbe.java b/src/recipeIntegrationTest/java/zone/moddev/mc/mineralogy/fixture/RecipeIntegrationProbe.java index a44bfa4a2..a5ac89295 100644 --- a/src/recipeIntegrationTest/java/zone/moddev/mc/mineralogy/fixture/RecipeIntegrationProbe.java +++ b/src/recipeIntegrationTest/java/zone/moddev/mc/mineralogy/fixture/RecipeIntegrationProbe.java @@ -96,7 +96,7 @@ private void serverStarted(ServerStartedEvent event) { } ItemStack result = recipe.assemble(inventory(name, - enabled ? basalt : Blocks.COBBLESTONE.asItem()), level.registryAccess()); + enabled ? basalt : Blocks.COBBLESTONE.asItem())); require(expectedOutput(name).equals(BuiltInRegistries.ITEM.getKey(result.getItem())), name + " produced " + BuiltInRegistries.ITEM.getKey(result.getItem())); require(result.getCount() == (isTrimTemplateRecipe(name) ? 2 : expectedCount(name)), @@ -241,7 +241,7 @@ private static void assertStoneSpearInput(ServerLevel level, CraftingRecipe reci CraftingInput input = stoneSpearInput(material); require(recipe.matches(input, level), "stone spear rejected " + BuiltInRegistries.ITEM.getKey(material)); - ItemStack output = recipe.assemble(input, level.registryAccess()); + ItemStack output = recipe.assemble(input); require(output.getItem() == expected && output.getCount() == 1, "stone spear produced the wrong result"); } @@ -258,7 +258,7 @@ private static void verifySlabRoutes(ServerLevel level) { CraftingInput slabInput = shaped(new String[] { "###" }, Map.of('#', nativeRock)); require(slab.matches(slabInput, level), family + " slab override does not match"); require(Identifier.fromNamespaceAndPath("mineralogy", family + "_slab").equals( - BuiltInRegistries.ITEM.getKey(slab.assemble(slabInput, level.registryAccess()).getItem())), + BuiltInRegistries.ITEM.getKey(slab.assemble(slabInput).getItem())), family + " slab override did not produce Mineralogy's slab"); assertBridge(level, family + "_slab_to_vanilla", @@ -300,7 +300,7 @@ private static void verifyTuffSlabRoutes(ServerLevel level) { CraftingRecipe slab = requireCraftingRecipe(level, form[1]); CraftingInput input = shaped(new String[] { "###" }, Map.of('#', source)); require(slab.matches(input, level), form[1] + " override does not match"); - ItemStack result = slab.assemble(input, level.registryAccess()); + ItemStack result = slab.assemble(input); require(result.getItem() == mineralogySlab && result.getCount() == 6, form[1] + " override did not produce six matching Mineralogy slabs"); @@ -391,7 +391,7 @@ private static void assertStonecutting(ServerLevel level, String name, Item sour StonecutterRecipe recipe = (StonecutterRecipe) holder.value(); SingleRecipeInput input = new SingleRecipeInput(new ItemStack(source)); require(recipe.matches(input, level), name + " does not match its native source"); - ItemStack output = recipe.assemble(input, level.registryAccess()); + ItemStack output = recipe.assemble(input); require(output.getItem() == expected && output.getCount() == expectedCount, name + " produced the wrong stonecutting result"); } @@ -400,7 +400,7 @@ private static void assertCrafting(ServerLevel level, String name, CraftingInput Item expected, int expectedCount) { CraftingRecipe recipe = requireCraftingRecipe(level, name); require(recipe.matches(input, level), name + " does not match its native inputs"); - ItemStack output = recipe.assemble(input, level.registryAccess()); + ItemStack output = recipe.assemble(input); require(output.getItem() == expected && output.getCount() == expectedCount, name + " produced the wrong native result"); } @@ -409,7 +409,7 @@ private static void assertBridge(ServerLevel level, String name, Item source, It CraftingRecipe recipe = requireCraftingRecipe(level, name, "mineralogy"); CraftingInput input = shapeless(source); require(recipe.matches(input, level), name + " does not match its exact source"); - ItemStack output = recipe.assemble(input, level.registryAccess()); + ItemStack output = recipe.assemble(input); require(output.getItem() == expected && output.getCount() == 1, name + " did not produce its exact one-for-one result"); } diff --git a/src/recipeIntegrationTest/resources/META-INF/neoforge.mods.toml b/src/recipeIntegrationTest/resources/META-INF/neoforge.mods.toml index a69660d4e..b1f01dba8 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="[21.11.45,21.12)" +versionRange="[26.1.2.94,26.1.3)" ordering="NONE" side="BOTH" [[dependencies.mineralogyrecipeprobe]] modId="mineralogy" type="required" -versionRange="[6.1.2.121112]" +versionRange="[6.1.2.2601022]" ordering="AFTER" side="BOTH" diff --git a/src/recipeIntegrationTest/resources/pack.mcmeta b/src/recipeIntegrationTest/resources/pack.mcmeta index 8f37e9bf4..cd2de0b08 100644 --- a/src/recipeIntegrationTest/resources/pack.mcmeta +++ b/src/recipeIntegrationTest/resources/pack.mcmeta @@ -1,6 +1,7 @@ { "pack": { "description": "Mineralogy recipe integration fixture", - "pack_format": 34 + "max_format": 101, + "min_format": [101, 1] } } diff --git a/src/test/java/zone/moddev/mc/mineralogy/GameplayContractTest.java b/src/test/java/zone/moddev/mc/mineralogy/GameplayContractTest.java index d3b1139e7..ef4e26212 100644 --- a/src/test/java/zone/moddev/mc/mineralogy/GameplayContractTest.java +++ b/src/test/java/zone/moddev/mc/mineralogy/GameplayContractTest.java @@ -135,7 +135,7 @@ public void cobblestonePolicyReappliesAfterReloadAndKeepsSpecialCases() throws E } @Test - public void forge61ConstructionReceivesStableIdsBeforeRegistration() throws Exception { + public void neoForge261ConstructionReceivesStableIdsBeforeRegistration() throws Exception { String helper = text("src/main/java/zone/moddev/mc/mineralogy/init/RegistrationProperties.java"); assertTrue(helper.contains("properties.setId(ResourceKey.create(Registries.BLOCK")); assertTrue(helper.contains("properties.setId(ResourceKey.create(Registries.ITEM")); @@ -157,7 +157,7 @@ public void optionalGunpowderDustsCannotCollapseToTwoIngredients() throws Except } @Test - public void neoForge2111UsesModelBlockLayersAndNativeFlowingFluidRendering() throws Exception { + public void neoForge261UsesNativeFluidModelRegistration() throws Exception { String fluid = text("src/main/java/zone/moddev/mc/mineralogy/init/MineralogyFluids.java"); assertTrue(fluid.contains("BaseFlowingFluid.Source")); assertTrue(fluid.contains("BaseFlowingFluid.Flowing")); @@ -170,9 +170,12 @@ public void neoForge2111UsesModelBlockLayersAndNativeFlowingFluidRendering() thr assertTrue(bucketModel.contains("\"layer0\": \"mineralogy:items/crude_oil_bucket\"")); assertFalse(bucketModel.contains("forge:fluid_container")); String client = text("src/main/java/zone/moddev/mc/mineralogy/client/ClientSetup.java"); - assertTrue(client.contains("ItemBlockRenderTypes.setRenderLayer(MineralogyFluids.CRUDE_OIL.get()")); - assertTrue(client.contains("ChunkSectionLayer.TRANSLUCENT")); - assertFalse(client.contains("setRenderLayer(block")); + assertTrue(client.contains("RegisterFluidModelsEvent")); + assertTrue(client.contains("FluidModel.Unbaked")); + assertTrue(client.contains("new Material(CRUDE_OIL_STILL, true)")); + assertTrue(client.contains("new Material(CRUDE_OIL_FLOW, true)")); + assertTrue(client.contains("event.register(model, MineralogyFluids.CRUDE_OIL,")); + assertFalse(client.contains("ItemBlockRenderTypes.setRenderLayer")); for (String model : new String[] { "pane_n", "pane_ne", "pane_ns", "pane_nse", "pane_nsew", "rocksaltlamp", "rocksaltlamp_down", "rocksaltlamp_wall", "rocksaltstreetlamp" }) { assertTrue(text("src/main/resources/assets/mineralogy/models/block/" + model + ".json") @@ -195,6 +198,10 @@ public void legacyWorldConversionPreservesIndexedChunksAndFurnaces() throws Exce assertTrue(transformer.contains("SimpleRegionStorage.class")); assertTrue(transformer.contains("prepareLegacyChunk")); assertTrue(transformer.contains("finalizeLegacyChunk")); + assertTrue(transformer.contains("upgradeChunkTag(Lnet/minecraft/nbt/CompoundTag;I" + + "Lnet/minecraft/nbt/CompoundTag;I)Lnet/minecraft/nbt/CompoundTag;")); + assertTrue(hook.contains("new File(worldDirectory, \"region\")")); + assertTrue(hook.contains("dimensions/minecraft/overworld/region")); String mappings = text("src/main/java/zone/moddev/mc/mineralogy/patching/PatchHandler.java"); assertTrue(mappings.contains("GRASS_PATH")); @@ -239,6 +246,26 @@ public void legacyFlatteningUsesTheExpandedArrayAndReinstallsTheSelectedWorldMap assertTrue(build.contains("Eclipse output is missing ${relative}")); } + @Test + public void minecraft2612UsesJava25WorldItemAndFurnaceApis() throws Exception { + String ore = text("src/main/java/zone/moddev/mc/mineralogy/blocks/Ore.java"); + assertTrue(ore.contains("builder.getLevel().getRandom()")); + + String rock = text("src/main/java/zone/moddev/mc/mineralogy/blocks/Rock.java"); + assertTrue(rock.contains("ItemInstance toolInstance")); + assertTrue(rock.contains("toolInstance instanceof ItemStack tool")); + + String fertilizer = text("src/main/java/zone/moddev/mc/mineralogy/items/MineralFertilizer.java"); + assertTrue(fertilizer.contains("ItemStack phantomBonemeal = new ItemStack(Items.BONE_MEAL, 27)")); + + String furnace = text("src/main/java/zone/moddev/mc/mineralogy/tileentity/TileEntityRockFurnace.java"); + assertTrue(furnace.contains("ItemStackTemplate remainder = fuel.getCraftingRemainder()")); + assertTrue(furnace.contains("recipe.value().assemble(new SingleRecipeInput(input))")); + + String reload = text("src/main/java/zone/moddev/mc/mineralogy/mixin/ReloadableServerResourcesMixin.java"); + assertTrue(reload.contains("updateComponentsAndStaticRegistryTags")); + } + private static String text(String path) throws Exception { return new String(Files.readAllBytes(new File(path).toPath()), StandardCharsets.UTF_8); } diff --git a/src/test/java/zone/moddev/mc/mineralogy/LocalizationQualityTest.java b/src/test/java/zone/moddev/mc/mineralogy/LocalizationQualityTest.java index c588dd7a2..d18be867b 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 1.21.11 JSON localization inventory. */ +/** Quality policy for the reviewed 26.1.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 c73028f50..3803bb7d1 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 21.11 common setup must not resolve unbound host tags", + assertFalse("NeoForge 26.1 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()) { @@ -129,7 +129,7 @@ public void everyRecipeHasAProgressiveAdvancement() throws Exception { } @Test - public void advancementsUseMinecraft1206HolderSetPredicateSchema() throws Exception { + public void advancementsUseMinecraft2612HolderSetPredicateSchema() throws Exception { File mineralogy = new File(ROOT, "data/mineralogy/advancement"); for (File file : jsonFiles(mineralogy)) { JsonObject advancement = json(file); @@ -454,15 +454,15 @@ public void allSeventeenLocalesHaveOrdered938KeyParity() throws Exception { } @Test - public void neoForge211ResourcesRetainNativeWallsTagsAndPackFormats() throws Exception { + public void neoForge261ResourcesRetainNativeWallsTagsAndPackFormats() throws Exception { JsonObject pack = json(new File(ROOT, "pack.mcmeta")); - assertEquals(94, pack.getAsJsonObject("pack").get("max_format").getAsInt()); + assertEquals(101, pack.getAsJsonObject("pack").get("max_format").getAsInt()); JsonArray dataMinimum = pack.getAsJsonObject("pack").getAsJsonArray("min_format"); - assertEquals(94, dataMinimum.get(0).getAsInt()); + assertEquals(101, dataMinimum.get(0).getAsInt()); assertEquals(1, dataMinimum.get(1).getAsInt()); JsonObject resourcePack = json(new File("resourcepack/x16/pack.mcmeta")); - assertEquals(75, resourcePack.getAsJsonObject("pack").get("min_format").getAsInt()); - assertEquals(75, resourcePack.getAsJsonObject("pack").get("max_format").getAsInt()); + assertEquals(84, resourcePack.getAsJsonObject("pack").get("min_format").getAsInt()); + assertEquals(84, 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")); @@ -537,12 +537,15 @@ public void neoForge211ResourcesRetainNativeWallsTagsAndPackFormats() throws Exc } @Test - public void integrationFixturesUsePack34AndSingularDataDirectories() throws Exception { + public void integrationFixturesUseDataFormat101AndSingularDataDirectories() 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, 34, - pack.getAsJsonObject("pack").get("pack_format").getAsInt()); + assertEquals(sourceSet, 101, + pack.getAsJsonObject("pack").get("max_format").getAsInt()); + JsonArray minimum = pack.getAsJsonObject("pack").getAsJsonArray("min_format"); + assertEquals(sourceSet, 101, 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()); assertFalse(sourceSet, new File(fixtureRoot, "data/forge/tags/items").exists()); @@ -663,8 +666,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.121112")); - assertTrue(properties.contains("orespawn_curse_file_id=8809764")); + assertTrue(properties.contains("mod_version=6.1.2.2601022")); + assertTrue(properties.contains("orespawn_curse_file_id=8809908")); 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")); diff --git a/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java b/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java index e708f8a0e..c0a8fd1e7 100644 --- a/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/mineralogy/WorkflowContractTest.java @@ -19,19 +19,19 @@ public void releaseMetadataIdentifiesTheGenericNeoForgeTarget() throws Exception try (FileInputStream input = new FileInputStream("gradle.properties")) { properties.load(input); } - assertEquals("6.1.2.121112", properties.getProperty("mod_version")); - assertEquals("1.21.11", properties.getProperty("minecraft_version")); + assertEquals("6.1.2.2601022", properties.getProperty("mod_version")); + assertEquals("26.1.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")); - assertEquals("21", properties.getProperty("java_version")); - assertEquals("21.0.7+6", properties.getProperty("java_toolchain_version")); - assertEquals("21", properties.getProperty("gradle_java_version")); + assertEquals("25", properties.getProperty("java_version")); + assertEquals("25.0.3+9", properties.getProperty("java_toolchain_version")); + 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.121112", properties.getProperty("orespawn_version")); - assertEquals("8809764", properties.getProperty("orespawn_curse_file_id")); - assertEquals("F7F2840D11090EC3B6A7A73AD380CFCAC3C034D3C8FCD9914CA1AAD4219E19E9", + assertEquals("4.0.16.2601022", properties.getProperty("orespawn_version")); + assertEquals("8809908", properties.getProperty("orespawn_curse_file_id")); + assertEquals("4F6612B89FC65E4860E962E8EA45CC03B752330060B3362112EBEBC7AA9C2E6C", properties.getProperty("orespawn_sha256")); String wrapper = text("gradle/wrapper/gradle-wrapper.properties"); assertTrue(wrapper.contains("gradle-9.2.1-bin.zip")); @@ -44,9 +44,9 @@ 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-1.21.11-neo")); - assertTrue(ci.contains("java-version: '21.0.7+6.0.LTS'")); - assertTrue(ci.contains("Install exact Java 21")); + assertTrue(ci.contains("master-26.1.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")); assertTrue(ci.contains("verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums")); assertTrue(ci.contains("eclipse verifyEclipseProductionClasspath")); @@ -59,7 +59,7 @@ public void ciAndSecurityChecksUsePinnedTargetNativeBuilds() throws Exception { assertTrue(staging.contains("https://www.curseforge.com/api/v1/mods/$project_id/files/$file_id/download")); assertTrue(staging.contains("sha256sum")); assertTrue(codeql.contains("github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28")); - assertTrue(codeql.contains("Install exact Java 21")); + assertTrue(codeql.contains("Install exact Java 25")); assertTrue(codeql.contains("clean classes --no-daemon --stacktrace --max-workers=2")); assertFalse(codeql.contains("Mavenizer")); assertTrue(wrapper.contains("gradle/actions/wrapper-validation@9c971963bec38e04b3d30dcc455b5382be2fdbfb")); @@ -87,9 +87,9 @@ 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 21.11 uses official names")); + assertTrue(build.contains("NeoForge 26.1 uses official names")); assertTrue(build.contains("'zone/moddev/mc/mineralogy/Mineralogy.class'")); - assertTrue(build.contains("928 NeoForge 21.11 item definitions")); + assertTrue(build.contains("928 NeoForge 26.1.2 item definitions")); assertTrue(build.contains("assets/mineralogy/items/")); assertTrue(build.contains("def preparedReleaseDir = project.findProperty('preparedReleaseDir')")); assertTrue(build.contains("tasks.register('verifyPreparedReleaseArtifacts')"));