diff --git a/.github/verify-base-metals-pin.sh b/.github/verify-base-metals-pin.sh new file mode 100644 index 00000000..fac90713 --- /dev/null +++ b/.github/verify-base-metals-pin.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +commit="$(sed -n 's/^basemetals_source_commit=//p' gradle.properties)" +if [[ ! "$commit" =~ ^[0-9a-f]{40}$ ]]; then + echo "::error::Expected a full Base Metals source commit in gradle.properties" + exit 1 +fi + +branch=master-1.20.1 +if ! status="$(gh api "repos/MinecraftModDevelopmentMods/BaseMetals/compare/$commit...$branch" --jq '.status')"; then + echo "::error::Could not verify Base Metals $commit on upstream $branch" + exit 1 +fi +case "$status" in + identical|ahead) printf 'commit=%s\n' "$commit" >> "$GITHUB_OUTPUT" ;; + *) echo "::error::Base Metals $commit is not on upstream $branch ($status). Local-only pins cannot qualify hosted CI." + exit 1 ;; +esac diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d49dabe0..9a91f969 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,16 @@ -name: basePower 1.19 CI +name: basePower 1.20.1 CI on: push: - branches: [master-1.19.4, 'feature/**'] + branches: [master-1.20.1, 'feature/**'] pull_request: - branches: [master-1.19.4] + branches: [master-1.20.1] permissions: contents: read concurrency: - group: basepower-1.19-${{ github.workflow }}-${{ github.ref }} + group: basepower-1.20.1-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -21,20 +21,24 @@ jobs: steps: - name: Check out PowerAdvantage uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - name: Require the Base Metals pin on upstream master-1.20.1 + id: base-metals-pin + env: + GH_TOKEN: ${{ github.token }} + run: bash .github/verify-base-metals-pin.sh + - name: Use canonical LF dependency inputs + run: git config --global core.autocrlf false - name: Check out pinned OreSpawn uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/OreSpawn - ref: 444d86ef48db2bf54422901b067c51d5832197fc + ref: 9d9db6cd315c9fce542808aa2551c94bf9267e93 path: .ci-dependencies/OreSpawn - - name: Use canonical LF dependency inputs - # Use the same source bytes on hosted and local dependency builds. - run: git config --global core.autocrlf false - name: Check out pinned Base Metals uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/BaseMetals - ref: a9fdd6842f2a2e1e2e5b9a0abf9178d5675df044 + ref: ${{ steps.base-metals-pin.outputs.commit }} path: .ci-dependencies/BaseMetals - name: Install pinned Java 25 Mavenizer runtime uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 @@ -71,8 +75,8 @@ jobs: chmod +x "$orespawn/gradlew" "$basemetals/gradlew" (cd "$orespawn" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar --no-daemon --stacktrace) (cd "$basemetals" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar --no-daemon --stacktrace) - osjar="$orespawn/build/libs-dev/OreSpawn-4.1.0.119041-deobf.jar" - bmjar="$basemetals/build/libs-dev/BaseMetals-3.1.2.119041-deobf.jar" + osjar="$orespawn/build/libs-dev/OreSpawn-4.1.0.120011-deobf.jar" + bmjar="$basemetals/build/libs-dev/BaseMetals-3.1.2.120011-deobf.jar" test -f "$osjar" && test -f "$bmjar" echo "orespawn=$osjar" >> "$GITHUB_OUTPUT" echo "basemetals=$bmjar" >> "$GITHUB_OUTPUT" @@ -83,25 +87,25 @@ jobs: writeReleaseChecksums verifyEclipseProductionClasspath -PbaseMetalsDeobfJar=${{ steps.dependencies.outputs.basemetals }} -PoreSpawnDeobfJar=${{ steps.dependencies.outputs.orespawn }} - -Pforge45MavenizerJar=${{ steps.dependencies.outputs.mavenizer }} + -Pforge47MavenizerJar=${{ steps.dependencies.outputs.mavenizer }} --no-daemon --stacktrace - name: Upload audited release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: basePower-1.19.4-${{ github.sha }} + name: basePower-1.20.1-${{ github.sha }} if-no-files-found: error retention-days: 30 path: | - build/libs/basePower-2.4.11.119041.jar - build/libs/basePower-2.4.11.119041-sources.jar - build/libs/basePower-2.4.11.119041-javadoc.jar + build/libs/basePower-2.4.12.120011.jar + build/libs/basePower-2.4.12.120011-sources.jar + build/libs/basePower-2.4.12.120011-javadoc.jar build/release/SHA256SUMS CHANGELOG.txt - name: Upload diagnostics on failure if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: basePower-1.19.4-diagnostics-${{ github.sha }} + name: basePower-1.20.1-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 d0fd9336..894b582a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,9 +2,9 @@ name: CodeQL on: push: - branches: [master-1.19.4, 'feature/**'] + branches: [master-1.20.1, 'feature/**'] pull_request: - branches: [master-1.19.4] + branches: [master-1.20.1] schedule: - cron: '47 7 * * 4' @@ -21,20 +21,24 @@ jobs: steps: - name: Check out PowerAdvantage uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - name: Require the Base Metals pin on upstream master-1.20.1 + id: base-metals-pin + env: + GH_TOKEN: ${{ github.token }} + run: bash .github/verify-base-metals-pin.sh + - name: Use canonical LF dependency inputs + run: git config --global core.autocrlf false - name: Check out pinned OreSpawn uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/OreSpawn - ref: 444d86ef48db2bf54422901b067c51d5832197fc + ref: 9d9db6cd315c9fce542808aa2551c94bf9267e93 path: .ci-dependencies/OreSpawn - - name: Use canonical LF dependency inputs - # Use the same source bytes on hosted and local dependency builds. - run: git config --global core.autocrlf false - name: Check out pinned Base Metals uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/BaseMetals - ref: a9fdd6842f2a2e1e2e5b9a0abf9178d5675df044 + ref: ${{ steps.base-metals-pin.outputs.commit }} path: .ci-dependencies/BaseMetals - name: Install pinned Java 25 Mavenizer runtime uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 @@ -71,19 +75,20 @@ jobs: chmod +x "$orespawn/gradlew" "$basemetals/gradlew" (cd "$orespawn" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar --no-daemon --stacktrace) (cd "$basemetals" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar --no-daemon --stacktrace) - echo "orespawn=$orespawn/build/libs-dev/OreSpawn-4.1.0.119041-deobf.jar" >> "$GITHUB_OUTPUT" - echo "basemetals=$basemetals/build/libs-dev/BaseMetals-3.1.2.119041-deobf.jar" >> "$GITHUB_OUTPUT" + echo "orespawn=$orespawn/build/libs-dev/OreSpawn-4.1.0.120011-deobf.jar" >> "$GITHUB_OUTPUT" + echo "basemetals=$basemetals/build/libs-dev/BaseMetals-3.1.2.120011-deobf.jar" >> "$GITHUB_OUTPUT" echo "mavenizer=$mavenizer" >> "$GITHUB_OUTPUT" - name: Initialize CodeQL uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4 with: languages: java-kotlin + build-mode: manual - name: Compile production code run: | chmod +x ./gradlew - ./gradlew $MMD_GRADLE_TOOLCHAINS clean classes --rerun-tasks --no-build-cache --no-daemon --stacktrace \ + ./gradlew $MMD_GRADLE_TOOLCHAINS clean classes verifyReleaseDependencies --rerun-tasks --no-build-cache --no-daemon --stacktrace \ -PbaseMetalsDeobfJar=${{ steps.dependencies.outputs.basemetals }} \ -PoreSpawnDeobfJar=${{ steps.dependencies.outputs.orespawn }} \ - -Pforge45MavenizerJar=${{ steps.dependencies.outputs.mavenizer }} + -Pforge47MavenizerJar=${{ steps.dependencies.outputs.mavenizer }} - name: Analyze uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4 diff --git a/.github/workflows/release-on-tag.yml b/.github/workflows/release-on-tag.yml index 31febbbd..3ca3a8d7 100644 --- a/.github/workflows/release-on-tag.yml +++ b/.github/workflows/release-on-tag.yml @@ -65,11 +65,12 @@ jobs: exit 1 fi - successful_ci="$(gh api \ - "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/check-runs?per_page=100" \ - --jq '[.check_runs[] | select(.name == "Build, test, and audit" and .conclusion == "success")] | length')" + successful_ci="$(gh api --method GET \ + "repos/$GITHUB_REPOSITORY/actions/workflows/ci.yml/runs" \ + -f head_sha="$GITHUB_SHA" -f branch="master-$minecraft_version" \ + -f event=push -f status=success --jq '.total_count')" if [[ "$successful_ci" -lt 1 ]]; then - echo "The tagged commit has no successful Build, test, and audit check" >&2 + echo "The tagged commit has no successful push CI on master-$minecraft_version" >&2 exit 1 fi @@ -80,10 +81,10 @@ jobs: { echo "## Release candidate validated" echo - echo "Tag \`$GITHUB_REF_NAME\` matches this target and has a successful Build, test, and audit check." + echo "Tag \`$GITHUB_REF_NAME\` matches this target and has successful push CI on its release branch." echo echo "**Nothing has been published.**" echo echo "Live publication requires \`deploy-release.yml\` on the repository default branch." - echo "Once that guarded dispatcher is installed, continue at: $RELEASE_WORKFLOW_URL" + echo "After the exact CI artifact is approved and registered, continue at: $RELEASE_WORKFLOW_URL" } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/validate-gradle-build.yml b/.github/workflows/validate-gradle-build.yml index 2d52c08f..63abc33f 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.19.4 + - master-1.20.1 - 'feature/**' pull_request: branches: - - master-1.19.4 + - master-1.20.1 permissions: contents: read diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7a1faeb0..916fc0dd 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,12 @@ +basePower 2.4.12.120011 (Minecraft 1.20.1, Forge 47) + +- Bring basePower to Forge 47 with the same blocks, items, and machine data. +- Use Minecraft's current screen rendering, creative tabs, and block properties. +- Keep all three mods on one creative tab and retain the old recipe unlocks. +- Keep the shared world upgrade hook so old machine facings, item wear and contents can be read before Minecraft converts the chunks. +- Map the renamed vanilla pottery and sound entries so 1.19.4 worlds open without a missing registry warning. +- Requires MMD OreSpawn 4.1.0.120011. If your world already uses Base Metals, keep it installed and upgrade to 3.1.2.120011 before opening a copy of the world. + basePower 2.4.11.119041 (Minecraft 1.19.4) - Bring basePower to Forge 45 and Java 17 without renaming existing machines or items. diff --git a/README.md b/README.md index 68426971..31c8f0f7 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,29 @@ # basePower -**Minecraft 1.19.4, version 2.4.11.119041.** +**Minecraft 1.20.1, Forge 47.4.10, Java 17.** -See the [1.19 port record](docs/1.19/PORT-STATUS.md) for the current checks. +This branch prepares basePower `2.4.12.120011`. It is not a download announcement. + +See the [1.20.1 port record](docs/1.20.1/PORT-STATUS.md) for the current checks. Results from earlier versions do not qualify this build. basePower continues DrCyano's Power Advantage. It provides shared power, fluids and item transport for baseSteam and baseElectric. +## Playing On 1.20.1 + +- Install [MMD OreSpawn 4.1.0.120011](https://www.curseforge.com/minecraft/mc-mods/mmd-orespawn/files/9175609) on both client and server. +- Base Metals is optional for a new basePower world. For a world that already + uses Base Metals, keep it installed and use the matching Forge 1.20.1 build + `3.1.2.120011`. Older Base Metals builds do not have the shared upgrade hook. +- baseSteam and baseElectric are separate mods. Use only their matching + 1.20.1 builds. Additional Loot Tables is not needed on 1.20.1. + **Back up the entire world before upgrading. Test only disposable copies.** The port keeps existing registry names and machine data. The upgrade checks use disposable copies of original Advantage and released base* saves, including connected machines, and check them again after a full restart. Check that the -other mods in your world support 1.19.4 before you upgrade. +other mods in your world support 1.20.1 before you upgrade. The accepted [1.14 results](docs/1.14/BROADER-QUALIFICATION.md) are historical evidence, not qualification of this port or a whole modpack. @@ -20,44 +31,46 @@ Recipe-book discovery now follows relevant ingredients. See the [all-Advantage m The [manufacturing progression audit](docs/1.13/MANUFACTURING-PROGRESSION.md) traces survival parts from raw resources, including configured material aliases, processing, loot-only parts and automated restart checks. -## Building Minecraft 1.19.4 +## Building Minecraft 1.20.1 -The build uses Forge 45.4.0, official `1.19.4` mappings, -MCP `20230314.122934`, ForgeGradle 7.0.34 and Gradle 9.6.1. +The build uses Forge 47.4.10, official `1.20.1` mappings, +MCP `20230612.114412`, ForgeGradle 7.0.34 and Gradle 9.6.1. Use Java 17 for Gradle, compilation and Minecraft. Mavenizer also needs Java 25. CI pins these JDKs and Java 8 for the legacy renamer. Pass the installed homes using `-Porg.gradle.java.installations.paths=,,` and disable automatic discovery and downloads for a reproducibility check. -Build the pinned Base Metals `3.1.2.119041` and OreSpawn `4.1.0.119041` deobf jars first. +Build the pinned Base Metals `3.1.2.120011` and OreSpawn `4.1.0.120011` deobf jars first. The source pins and checksums are in `gradle.properties`. -Forge 45 also needs the Mavenizer compatibility jar in the pinned OreSpawn +Forge 47 also needs the Mavenizer compatibility jar in the pinned OreSpawn checkout's `ci-fixtures/tools/` directory. It fixes decompiled Forge sources on a clean build and uses Java 25. It is not part of the mod or game runtime. -Set `-Pforge45MavenizerJar=` when that checkout is in another location. -Use Base Metals 3.1.2 if it is installed when upgrading a world. It lets +Set `-Pforge47MavenizerJar=` when that checkout is in another location. +If Base Metals is installed, use the pinned 3.1.2 build when testing an upgrade. It lets both mods preserve old items and machines before Minecraft converts the chunk. An older Base Metals jar is not a substitute for this upgrade path. Then run from the repository root: ```text -gradlew.bat clean check build javadoc verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums verifyEclipseProductionClasspath +gradlew.bat clean check build javadoc genEclipseRuns eclipse isolateEclipseProductionRuns verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums verifyEclipseProductionClasspath ``` The default dependency jars are: ```text -D:\BaseMetals\BaseMetals 119\BaseMetals\build\libs-dev\BaseMetals-3.1.2.119041-deobf.jar -D:\MinecraftMineralogy\OS119\OreSpawn\build\libs-dev\OreSpawn-4.1.0.119041-deobf.jar +D:\BaseMetals\BaseMetals 1201\BaseMetals\build\libs-dev\BaseMetals-3.1.2.120011-deobf.jar +D:\MinecraftMineralogy\OS1201\OreSpawn\build\libs-dev\OreSpawn-4.1.0.120011-deobf.jar ``` Other layouts can pass `-PbaseMetalsDeobfJar=` and `-PoreSpawnDeobfJar=`. Dependencies are never embedded in PowerAdvantage artifacts. Dependency checksums and source commits are recorded in `gradle.properties`. -Unknown artifacts fail the dependency audit. Archives use reproducible ordering, -LF text and no empty directories, so fresh checkouts produce the same bytes. +Unknown artifacts fail the dependency audit. The release audit also rejects a +player jar that differs from the frozen test kit. Hosted CI requires the Base +Metals pin to be on its upstream `master-1.20.1` branch; a locally tested pin +does not qualify a hosted build. Release jars are written to `build/libs`; `deobfJar` writes the sibling-development jar to `build/libs-dev`. @@ -71,10 +84,10 @@ Refresh the project in Eclipse, allow its Java build to finish, and launch the g Eclipse copies production resources from `build/resources/main`, not directly from `src/main/resources`. This prevents its builder from overwriting the expanded `mods.toml` with raw `${version}` placeholders. After updating this setup, use **Gradle > Refresh Gradle Project**, then **Project > Clean** before relaunching. After editing resources or version properties, run `processResources` or refresh the Gradle project before the Eclipse build. See the [metadata regression notes](docs/1.13/ECLIPSE-METADATA.md). -To prepare a combined client, build the baseSteam and baseElectric `2.2.12.119041` deobf jars, +To prepare a combined client, build the baseSteam and baseElectric `2.2.13.120011` deobf jars, run `gradlew.bat prepareCombinedEclipseLaunch`, refresh Eclipse, then launch `runClientAllAdvantage.launch`. Inputs must match -`test-rig/profiles/native119/dev-core.json`; alternative layouts can pass +`test-rig/profiles/native1201/dev-core.json`; alternative layouts can pass `-PsteamAdvantageDeobfJar=` and `-PelectricAdvantageDeobfJar=`. The ordinary `runClient.launch` remains Power-only. Both use the `run` directory; preparing a launch does not copy, open or qualify a save. @@ -109,6 +122,6 @@ data-pack tags. The shared pre-flattening migration hook remains necessary; its presence is not proof that an upgrade is safe. The [legacy migration guide](docs/1.13/MIGRATION.md) describes the earlier protocols. -The [1.19 status](docs/1.19/PORT-STATUS.md) tracks this port's qualification. +The [Advantage Works 1.20.1 guide](test-rig/NATIVE1201.md) lists the automated checks. The historical 1.10 handbook remains on the [1.10.2 branch](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.10.2/docs/1.10/README.md). diff --git a/build.gradle b/build.gradle index 20233c84..f548f7c9 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ plugins { id 'net.minecraftforge.gradle' version '7.0.34' } -apply from: 'gradle/forge45-mavenizer.gradle' +apply from: 'gradle/forge47-mavenizer.gradle' group = project.mod_group version = project.mod_version @@ -134,7 +134,7 @@ sourceSets.main.resources { def forgeRunModClassesDirectory = layout.buildDirectory.dir('forge-run-mod-classes/main') def prepareForgeRunModClasses = tasks.register('prepareForgeRunModClasses', Sync) { group = 'ide' - description = 'Merges classes and processed resources for Forge 1.19.4 launches.' + description = 'Merges classes and processed resources for Forge 1.20.1 launches.' dependsOn tasks.named('classes') from sourceSets.main.output into forgeRunModClassesDirectory @@ -169,10 +169,10 @@ repositories { // The default paths mirror the local MMD checkout layout without tying the // build to a drive letter. CI and other layouts can override either path. def baseMetalsDeobfJar = file(providers.gradleProperty('baseMetalsDeobfJar') - .getOrElse('../../../BaseMetals/BaseMetals 119/BaseMetals/build/libs-dev/' + .getOrElse('../../../BaseMetals/BaseMetals 1201/BaseMetals/build/libs-dev/' + "BaseMetals-${project.basemetals_version}-deobf.jar")) def oreSpawnDeobfJar = file(providers.gradleProperty('oreSpawnDeobfJar') - .getOrElse('../../../MinecraftMineralogy/OS119/OreSpawn/build/libs-dev/' + .getOrElse('../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs-dev/' + "OreSpawn-${project.orespawn_version}-deobf.jar")) dependencies { @@ -338,17 +338,17 @@ tasks.register('verifyReleaseConfiguration') { description = 'Validates release identity, target metadata, and optional integration policy.' doLast { def pack = new JsonSlurper().parse(file('src/main/resources/pack.mcmeta')).pack - if (pack.pack_format != 12 || pack['forge:resource_pack_format'] != 13 || pack['forge:data_pack_format'] != 12) { - throw new GradleException('Minecraft 1.19.4 requires resource pack format 13 and data pack format 12') + if (pack.pack_format != 15 || pack['forge:resource_pack_format'] != 15 || pack['forge:data_pack_format'] != 15) { + throw new GradleException('Minecraft 1.20.1 requires resource and data pack format 15') } - if (project.mod_version != '2.4.11.119041') { + if (project.mod_version != '2.4.12.120011') { throw new GradleException("Unexpected PowerAdvantage release version: ${project.mod_version}") } - if (project.minecraft_version != '1.19.4' - || project.forge_version != '45.4.0' + if (project.minecraft_version != '1.20.1' + || project.forge_version != '47.4.10' || project.mapping_channel != 'official' - || project.mapping_version != '1.19.4' - || project.mcp_version != '20230314.122934') { + || project.mapping_version != '1.20.1' + || project.mcp_version != '20230612.114412') { throw new GradleException('Unexpected Minecraft, Forge, or mappings target') } if (project.loader_name != 'forge' || project.loader_code != '1' @@ -363,21 +363,21 @@ tasks.register('verifyReleaseConfiguration') { || project.curseforge_project_id != '1780140') { throw new GradleException('Unexpected Forge, Maven, archive, or CurseForge identity') } - if (project.cf_requirements != 'base-metals,mmd-orespawn' - || project.cf_optionals != 'additional-loot-tables' - || project.cf_versions != '1.19.4') { + if (project.cf_requirements != 'mmd-orespawn' + || project.cf_optionals != 'base-metals' + || project.cf_versions != '1.20.1') { throw new GradleException('Unexpected CurseForge dependency or game-version metadata') } - if (project.basemetals_version != '3.1.2.119041' - || project.orespawn_version != '4.1.0.119041' - || project.basemetals_source_commit != 'a9fdd6842f2a2e1e2e5b9a0abf9178d5675df044' - || project.orespawn_source_commit != '444d86ef48db2bf54422901b067c51d5832197fc') { + if (project.basemetals_version != '3.1.2.120011' + || project.orespawn_version != '4.1.0.120011' + || !(project.basemetals_source_commit ==~ /[0-9a-f]{40}/) + || project.orespawn_source_commit != '9d9db6cd315c9fce542808aa2551c94bf9267e93') { throw new GradleException('Unexpected Base Metals or OreSpawn dependency identity') } String mainSource = file( 'src/main/java/zone/moddev/mc/basepower/PowerAdvantage.java').getText('UTF-8') if (!mainSource.contains('MODID = "basepower"') - || !mainSource.contains('VERSION = "2.4.11.119041"') + || !mainSource.contains('VERSION = "2.4.12.120011"') || !mainSource.contains('@Mod(PowerAdvantage.MODID)')) { throw new GradleException('PowerAdvantage source identity changed') } @@ -562,6 +562,11 @@ tasks.register('verifyReleaseArtifacts') { } File mainJar = new File(libs, expectedReleaseFiles.get()[0]) + String mainHash = MessageDigest.getInstance('SHA-256').digest(mainJar.bytes).encodeHex().toString() + if (!mainHash.equalsIgnoreCase(project.release_player_sha256 as String)) { + throw new GradleException("${mainJar.name} SHA-256 is ${mainHash}, " + + "expected frozen player jar ${project.release_player_sha256}") + } new ZipFile(mainJar).withCloseable { zip -> List names = zip.entries().collect { it.name } ['META-INF/mods.toml', 'META-INF/accesstransformer.cfg', 'pack.mcmeta', @@ -870,6 +875,17 @@ tasks.register('isolateEclipseProductionRuns') { String eclipseModClasses = "${project.mod_id}%%${mainOutput}" + "${File.pathSeparator}${project.mod_id}%%${mainOutput}" modClasses[0].@value = eclipseModClasses + def vmArguments = launchXml.stringAttribute.find { it.@key == 'org.eclipse.jdt.launching.VM_ARGUMENTS' } + if (vmArguments != null) { + // ForgeGradle leaves these path arguments bare even when a directory contains spaces. + vmArguments.@value = (vmArguments.@value as String) + .replaceAll(/(? + "\"${argument}\"" + } + .replaceAll(/(? + "-p \"${argument}\"" + } + } contents = groovy.xml.XmlUtil.serialize(launchXml) } launch.setText(contents.replace('\r\n', '\n'), 'UTF-8') @@ -1027,6 +1043,14 @@ tasks.register('verifyEclipseProductionClasspath') { ['runClient.launch', 'runServer.launch'].each { name -> def launch = new groovy.xml.XmlSlurper().parse(file(name)) String contents = file(name).getText('UTF-8').replace('\\', '/') + String vmArguments = launch.stringAttribute.find { + it.@key.text() == 'org.eclipse.jdt.launching.VM_ARGUMENTS' + }.@value.text() + def legacyFile = vmArguments =~ /(?:^|\s)"-DlegacyClassPath\.file=([^"]+)"(?=\s|$)/ + if (!legacyFile.find() || !file(legacyFile.group(1)).isFile() + || !(vmArguments =~ /(?:^|\s)-p\s+"[^"]+"/).find()) { + throw new GradleException("${name} must quote the Forge classpath and module paths") + } if (launch.booleanAttribute.find { it.@key.text() == 'org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE' }.@value.text() != 'true' @@ -1234,9 +1258,9 @@ tasks.register('clientResourceProbeJar', Jar) { // these deobf jars are runtime inputs, never release contents or compile dependencies. def advantageExtensionJars = [ basesteam: file(providers.gradleProperty('steamAdvantageDeobfJar').getOrElse( - '../SteamAdvantage/SteamAdvantage/build/libs-dev/baseSteam-2.2.12.119041-deobf.jar')), + '../SteamAdvantage/SteamAdvantage/build/libs-dev/baseSteam-2.2.13.120011-deobf.jar')), baseelectric: file(providers.gradleProperty('electricAdvantageDeobfJar').getOrElse( - '../ElectricAdvantage/ElectricAdvantage/build/libs-dev/baseElectric-2.2.12.119041-deobf.jar')) + '../ElectricAdvantage/ElectricAdvantage/build/libs-dev/baseElectric-2.2.13.120011-deobf.jar')) ] tasks.register('prepareCombinedEclipseLaunch') { @@ -1246,7 +1270,7 @@ tasks.register('prepareCombinedEclipseLaunch') { dependsOn tasks.named('deobfJar') doLast { File inputProfile = file(providers.gradleProperty('advantageDevelopmentProfile').getOrElse( - 'test-rig/profiles/native119/dev-core.json')) + 'test-rig/profiles/native1201/dev-core.json')) def profile = new JsonSlurper().parse(inputProfile) if (profile.powerDeobfSha256) { File powerJar = tasks.named('jar', Jar).get().archiveFile.get().asFile diff --git a/docs/1.20.1/PORT-STATUS.md b/docs/1.20.1/PORT-STATUS.md new file mode 100644 index 00000000..b6d38619 --- /dev/null +++ b/docs/1.20.1/PORT-STATUS.md @@ -0,0 +1,42 @@ +# Minecraft 1.20.1 port + +This local port starts from the 1.19.4 code. The candidates are basePower +`2.4.12.120011`, baseSteam and baseElectric `2.2.13.120011`, on Forge +`47.4.10` with Java 17. See the [Works rig](../../test-rig/NATIVE1201.md) for +reproduction steps and exact jar pins. No 1.20.1 release is implied. + +The port uses the current block properties, creative-tab registry and screen +drawing APIs. Saved registry names and machine data stay the same. The shared +Base Metals migration hook is still needed when upgrading legacy saves with +both mods installed. Use the pinned local Base Metals build for those tests. +The port also maps the old vanilla pottery and sound IDs in Forge's 1.19.4 +registry snapshot. Minecraft itself converts the saved pottery stacks. + +## What the tests check + +The broad Works sweep has 21 stations in each of two profiles, with and without +Base Metals. It checks machine output and saved state, including drill movement +and state after a full server restart. Its independent audit reads the raw +station results and fails if a profile or required checkpoint is missing. + +The migration checks use copies of original 1.10.2 Advantage saves, released +1.10.2 and 1.12.2 base* saves, and a 1.19.4 save. They compare saved state and +then operate the existing machines without replacing them. Keep the original +save and all its other mods safe before trying an upgrade yourself. + +The combined client check renders all 39 machine screens and checks both the +machine name and inventory caption. Deliberately missing and overlapping +labels must fail. It also checks the creative tab, models, textures and +recipe-book grouping with data from the server. + +The tested jars passed a 30-minute run in both a fresh world and a migrated +1.10.2 world, including a full restart. The optional-power fixture also kept +4,000 mB in the fluid tank across a restart without Base Metals installed. +The Nether and End checks still report one vanilla difference: a tamed wolf +loaded at 20 health instead of 8. Forge reproduced that without any mods. + +Manual checks should use the combined Eclipse launch or exact packaged +candidates: inspect models, recipe discovery and menus, then open a +disposable copy of an existing world. Pay particular attention to turbine +orientation and movement. The automated client check does not open a world +or exercise a real player's death screen. diff --git a/gradle.properties b/gradle.properties index 18bb32aa..d7012ab5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,15 +5,15 @@ org.gradle.caching=true org.gradle.parallel=false net.minecraftforge.gradle.merge-source-sets=false -minecraft_version=1.19.4 -minecraft_version_range=[1.19.4] -forge_version=45.4.0 -forge_installer_sha256=6643BB8C21F409CC528FF656DAF60C206D304CC77BF529BBBAB4B336004DFC53 -forge_version_range=[45.4.0,46) -loader_version_range=[45,) +minecraft_version=1.20.1 +minecraft_version_range=[1.20.1] +forge_version=47.4.10 +forge_installer_sha256=1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3 +forge_version_range=[47.4.10,48) +loader_version_range=[47,) mapping_channel=official -mapping_version=1.19.4 -mcp_version=20230314.122934 +mapping_version=1.20.1 +mcp_version=20230612.114412 loader_name=forge loader_code=1 @@ -26,21 +26,22 @@ curseforge_project_id=1780140 mod_id=basepower mod_name=basePower mod_license=LGPL-3.0-only -mod_version=2.4.11.119041 +mod_version=2.4.12.120011 +release_player_sha256=E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A mod_group=zone.moddev.mc.basepower mod_authors=DrCyano (aka Cyanobacterium) mod_description=API and shared machines for pressure, electricity, quantum power, fluids, and item transport. -cf_requirements=base-metals,mmd-orespawn -cf_optionals=additional-loot-tables -cf_versions=1.19.4 +cf_requirements=mmd-orespawn +cf_optionals=base-metals +cf_versions=1.20.1 -basemetals_version=3.1.2.119041 -basemetals_source_commit=a9fdd6842f2a2e1e2e5b9a0abf9178d5675df044 +basemetals_version=3.1.2.120011 +basemetals_source_commit=b4795d413b3d356406c351c5e7e29406789f3f30 basemetals_curse_project_id=240967 -basemetals_deobf_sha256=0AA993D6BADA54B11548EB5BE150CE0939232291F2D215B7DBAF149857976B2F +basemetals_deobf_sha256=A67EB0CB74971E53D528C4D4F1275AE007106D7F8F71DFE4A16FB50411BDCC28 -orespawn_version=4.1.0.119041 -orespawn_source_commit=444d86ef48db2bf54422901b067c51d5832197fc +orespawn_version=4.1.0.120011 +orespawn_source_commit=9d9db6cd315c9fce542808aa2551c94bf9267e93 orespawn_curse_project_id=245586 -orespawn_deobf_sha256=BE6973F68F1C310DFF8CDF89C12B34C62D68CAEA326C0F1528E486EE3ABC1000 +orespawn_deobf_sha256=A0B096894DC48308D59455F7EC67AB0BBF7EB02354D903024A9E9E876EB07CBB diff --git a/gradle/forge45-mavenizer.gradle b/gradle/forge47-mavenizer.gradle similarity index 56% rename from gradle/forge45-mavenizer.gradle rename to gradle/forge47-mavenizer.gradle index 298b4944..84465786 100644 --- a/gradle/forge45-mavenizer.gradle +++ b/gradle/forge47-mavenizer.gradle @@ -1,20 +1,20 @@ import java.security.MessageDigest import org.gradle.jvm.toolchain.JvmVendorSpec -// OreSpawn's audited Forge 45 fixture fixes eight decompiled record accessors. +// OreSpawn's audited Forge 47 fixture fixes decompiled record accessors. def tool = 'ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar' -def defaultJar = project.extensions.extraProperties.has('forge45MavenizerDefault') - ? project.forge45MavenizerDefault - : "../../../MinecraftMineralogy/OS119/OreSpawn/${tool}" -def fixture = file(providers.gradleProperty('forge45MavenizerJar').getOrElse(defaultJar)) -def expected = '341B3FB10ABA6EA7DC612FBE519DC290A1C81867AED5DD320ACD783688AC49DE' +def defaultJar = project.extensions.extraProperties.has('forge47MavenizerDefault') + ? project.forge47MavenizerDefault + : "../../../MinecraftMineralogy/OS1201/OreSpawn/${tool}" +def fixture = file(providers.gradleProperty('forge47MavenizerJar').getOrElse(defaultJar)) +def expected = '416DCA4797BC55826F0DDCF03FDC405F1990FC15C2133FA27A1F143BF7976177' if (!fixture.isFile()) { - throw new GradleException("Forge 45 requires OreSpawn's Mavenizer fixture: ${fixture}. " - + "Use -Pforge45MavenizerJar= for another checkout layout.") + throw new GradleException("Forge 47 requires OreSpawn's Mavenizer fixture: ${fixture}. " + + "Use -Pforge47MavenizerJar= for another checkout layout.") } def actual = MessageDigest.getInstance('SHA-256').digest(fixture.bytes).encodeHex().toString().toUpperCase(Locale.ROOT) if (actual != expected) { - throw new GradleException("Forge 45 Mavenizer fixture SHA-256 mismatch: expected ${expected}, got ${actual}") + throw new GradleException("Forge 47 Mavenizer fixture SHA-256 mismatch: expected ${expected}, got ${actual}") } fgtools.configure('mavenizer') { diff --git a/src/main/java/cyano/poweradvantage/api/ConduitBlock.java b/src/main/java/cyano/poweradvantage/api/ConduitBlock.java index f06b6433..49814def 100644 --- a/src/main/java/cyano/poweradvantage/api/ConduitBlock.java +++ b/src/main/java/cyano/poweradvantage/api/ConduitBlock.java @@ -1,7 +1,6 @@ package cyano.poweradvantage.api; import zone.moddev.mc.basepower.conduitnetwork.ConduitRegistry; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Explosion; @@ -24,19 +23,6 @@ * */ public abstract class ConduitBlock extends net.minecraft.world.level.block.Block implements ITypedConduit { - /** - * Block constructor - * - * @param mat Block material, typically Material.iron - */ - protected ConduitBlock(Material mat) { - this(mat, 1.0F); - } - - protected ConduitBlock(Material mat, float hardness) { - this(Properties.of(mat).strength(hardness)); - } - protected ConduitBlock(Properties properties) { super(properties); } diff --git a/src/main/java/cyano/poweradvantage/api/GUIBlock.java b/src/main/java/cyano/poweradvantage/api/GUIBlock.java index b7f828db..f066f9f0 100644 --- a/src/main/java/cyano/poweradvantage/api/GUIBlock.java +++ b/src/main/java/cyano/poweradvantage/api/GUIBlock.java @@ -1,6 +1,7 @@ package cyano.poweradvantage.api; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; +import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; @@ -37,17 +38,10 @@ */ public abstract class GUIBlock extends net.minecraft.world.level.block.BaseEntityBlock{ - /** - * Constructor for GUI block - * @param m Material for the block (determines what tools can break it and how it interacts with - * other Minecraft rules). - */ - public GUIBlock(Material m) { - this(m, 1.0F); - } - - public GUIBlock(Material m, float hardness) { - this(Block.Properties.of(m).strength(hardness).noOcclusion().dynamicShape()); + /** Defaults for machine blocks formerly made from the piston material. */ + public static Block.Properties machineProperties(float hardness) { + return Block.Properties.of().mapColor(MapColor.STONE).pushReaction(PushReaction.BLOCK) + .forceSolidOn().strength(hardness).noOcclusion().dynamicShape(); } protected GUIBlock(Block.Properties properties) { diff --git a/src/main/java/cyano/poweradvantage/api/fluid/FluidConduitBlock.java b/src/main/java/cyano/poweradvantage/api/fluid/FluidConduitBlock.java index 9e02292a..10fc56bd 100644 --- a/src/main/java/cyano/poweradvantage/api/fluid/FluidConduitBlock.java +++ b/src/main/java/cyano/poweradvantage/api/fluid/FluidConduitBlock.java @@ -4,7 +4,6 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.PowerConnectorContext; import zone.moddev.mc.basepower.init.Fluids; -import net.minecraft.world.level.material.Material; /** *

@@ -23,21 +22,8 @@ */ public abstract class FluidConduitBlock extends ConduitBlock { - /** - * Block constructor - * - * @param mat Block material, typically Material.iron - */ - protected FluidConduitBlock(Material mat) { - super(mat); - } - - /** - * Block constructor with the break hardness used by the standard conduit - * implementations. - */ - protected FluidConduitBlock(Material mat, float hardness) { - super(mat, hardness); + protected FluidConduitBlock(Properties properties) { + super(properties); } diff --git a/src/main/java/cyano/poweradvantage/api/modsupport/rf/BlockRFConverter.java b/src/main/java/cyano/poweradvantage/api/modsupport/rf/BlockRFConverter.java index 9f87dbe4..94400fcd 100644 --- a/src/main/java/cyano/poweradvantage/api/modsupport/rf/BlockRFConverter.java +++ b/src/main/java/cyano/poweradvantage/api/modsupport/rf/BlockRFConverter.java @@ -2,7 +2,6 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.simple.BlockSimplePowerMachine; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.core.BlockPos; @@ -12,9 +11,9 @@ public class BlockRFConverter extends BlockSimplePowerMachine { private final Class tileEntityClass; - public BlockRFConverter(Material material, float hardness, ConduitType type, + public BlockRFConverter(Properties properties, ConduitType type, Class tileEntityClass) { - super(material, hardness, type); + super(properties, type); this.tileEntityClass = tileEntityClass; } diff --git a/src/main/java/cyano/poweradvantage/api/modsupport/techreborn/BlockTRConverter.java b/src/main/java/cyano/poweradvantage/api/modsupport/techreborn/BlockTRConverter.java index b454a25a..c1ee9a3f 100644 --- a/src/main/java/cyano/poweradvantage/api/modsupport/techreborn/BlockTRConverter.java +++ b/src/main/java/cyano/poweradvantage/api/modsupport/techreborn/BlockTRConverter.java @@ -2,14 +2,13 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.modsupport.rf.BlockRFConverter; -import net.minecraft.world.level.material.Material; /** Historical Tech Reborn-labelled converter block, backed by Forge Energy. */ public class BlockTRConverter extends BlockRFConverter { @SuppressWarnings("unchecked") - public BlockTRConverter(Material material, float hardness, ConduitType type, + public BlockTRConverter(Properties properties, ConduitType type, Class tileEntityClass) { - super(material, hardness, type, + super(properties, type, (Class) tileEntityClass); } } diff --git a/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidConduit.java b/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidConduit.java index 3733536b..3f7f7ed2 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidConduit.java +++ b/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidConduit.java @@ -5,7 +5,6 @@ import cyano.poweradvantage.api.fluid.FluidConduitBlock; import zone.moddev.mc.basepower.util.PowerHelper; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.pathfinder.PathComputationType; @@ -31,8 +30,8 @@ public abstract class BlockSimpleFluidConduit extends FluidConduitBlock { private final double pipeRadius; - public BlockSimpleFluidConduit(Material material, float hardness, float pipeRadius) { - super(material, hardness); + public BlockSimpleFluidConduit(Block.Properties properties, float pipeRadius) { + super(properties); this.pipeRadius = pipeRadius; registerDefaultState(getStateDefinition().any() .setValue(WEST, false).setValue(DOWN, false).setValue(SOUTH, false) diff --git a/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidMachine.java b/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidMachine.java index 481d29dd..96333909 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidMachine.java +++ b/src/main/java/cyano/poweradvantage/api/simple/BlockSimpleFluidMachine.java @@ -1,7 +1,6 @@ package cyano.poweradvantage.api.simple; import zone.moddev.mc.basepower.init.Fluids; -import net.minecraft.world.level.material.Material; /** * This block class provides all of the standard code for creating a machine @@ -18,18 +17,6 @@ * */ public abstract class BlockSimpleFluidMachine extends BlockSimplePowerMachine { - /** - * Standard constructor for a machine block. - * - * @param blockMaterial This is the material for the block. Typically is set - * to net.minecraft.block.material.Material.piston, though any material can - * be used. - * @param hardness This affects how long it takes to break the block. 0.5 is - * a good value if you want it to be easy to break. - */ - public BlockSimpleFluidMachine(Material blockMaterial, float hardness) { - super(blockMaterial, hardness, Fluids.fluidConduit_general); - } protected BlockSimpleFluidMachine(net.minecraft.world.level.block.Block.Properties properties) { super(properties, Fluids.fluidConduit_general); diff --git a/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerConduit.java b/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerConduit.java index 5c918975..8113f598 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerConduit.java +++ b/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerConduit.java @@ -5,7 +5,6 @@ import cyano.poweradvantage.api.PowerConnectorContext; import zone.moddev.mc.basepower.util.PowerHelper; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.pathfinder.PathComputationType; @@ -29,11 +28,6 @@ public abstract class BlockSimplePowerConduit extends ConduitBlock { private final ConduitType[] types; private final double pipeRadius; - public BlockSimplePowerConduit(Material material, float hardness, float pipeRadius, - ConduitType... energyTypes) { - this(Block.Properties.of(material).strength(hardness), pipeRadius, energyTypes); - } - protected BlockSimplePowerConduit(Block.Properties properties, float pipeRadius, ConduitType... energyTypes) { super(properties); diff --git a/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerMachine.java b/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerMachine.java index e82fe5ee..eebc214d 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerMachine.java +++ b/src/main/java/cyano/poweradvantage/api/simple/BlockSimplePowerMachine.java @@ -3,7 +3,6 @@ import cyano.poweradvantage.api.*; import zone.moddev.mc.basepower.conduitnetwork.ConduitRegistry; import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.StateDefinition; @@ -41,32 +40,12 @@ * */ public abstract class BlockSimplePowerMachine extends GUIBlock implements ITypedConduit { + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; private final ConduitType[] type; - /** - * Blockstate property indicating which direction the block is facing - */ - public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; - /** - * Standard constructor for a machine block. Remember to set the GUI ID so that a GUI can pop-up - * when the player interacts with this block. - * @param blockMaterial This is the material for the block. Typically is set - * to net.minecraft.block.material.Material.piston, though any material can - * be used. - * @param hardness This affects how long it takes to break the block. 0.5 is - * a good value if you want it to be easy to break. - * @param energyType This is the energy type for this block. This is used by - * power conduits to determine whether to connect to this block. - */ - public BlockSimplePowerMachine(Material blockMaterial, float hardness, ConduitType... energyType){ - super(blockMaterial, hardness); - this.type = energyType; - this.registerDefaultState(this.getStateDefinition().any().setValue(FACING, Direction.NORTH)); - } /** - * 1.13 constructor for machines which need non-default block properties such - * as a different sound or blast resistance. + * Sets the block properties and the energy types accepted by this machine. */ protected BlockSimplePowerMachine(Block.Properties properties, ConduitType... energyType) { super(properties); diff --git a/src/main/java/cyano/poweradvantage/api/simple/SimpleMachineGUI.java b/src/main/java/cyano/poweradvantage/api/simple/SimpleMachineGUI.java index 7254d03b..5b772b6a 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/SimpleMachineGUI.java +++ b/src/main/java/cyano/poweradvantage/api/simple/SimpleMachineGUI.java @@ -4,6 +4,7 @@ import zone.moddev.mc.basepower.PowerAdvantage; import zone.moddev.mc.basepower.math.Integer2D; import zone.moddev.mc.basepower.registry.ITileEntityGUI; +import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Inventory; @@ -106,8 +107,7 @@ public SimpleMachineGUI(String guiImage, Integer2D... inventorySlotCoordinates){ * @param guiContainer This is the instance of GUIContainer that is drawing * the GUI. You need to use it to draw on the screen. For example:

-guiContainer.minecraft.getTextureManager().bindTexture(arrowTexture);
-guiContainer.blit(x+79, y+35, 0, 0, arrowLength, 17); // x, y, textureOffsetX, textureOffsetY, width, height)
+guiContainer.blit(arrowTexture, x+79, y+35, 0, 0, arrowLength, 17);
 	   
* @param x This is the x coordinate (in pixels) from the top-left corner of * the GUI @@ -248,7 +248,7 @@ else if (!this.moveItemStackTo(stackInSlot, 0, hostSize, false)) { public class GUIContainer extends net.minecraft.client.gui.screens.inventory.AbstractContainerScreen{ private final Object entity; private final Component playerInventoryLabel; - private PoseStack matrices = new PoseStack(); + private GuiGraphics graphics; public net.minecraft.client.Minecraft getMinecraft() { return minecraft; } public GUIContainer(Inventory playerItems, net.minecraft.world.Container entity) { @@ -265,21 +265,21 @@ public GUIContainer(Container container, Inventory playerItems, Component title) } @Override - public void render(PoseStack matrices, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(matrices); - super.render(matrices, mouseX, mouseY, partialTicks); - this.renderTooltip(matrices, mouseX, mouseY); + public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + this.renderBackground(graphics); + super.render(graphics, mouseX, mouseY, partialTicks); + this.renderTooltip(graphics, mouseX, mouseY); if (font.width(title.getString()) > width - 8 && mouseY >= topPos + 1 && mouseY < topPos + MACHINE_TOP) { - this.renderTooltip(matrices, title, mouseX, mouseY); + graphics.renderTooltip(font, title, mouseX, mouseY); } } @Override - protected void renderLabels(PoseStack matrices, int mouseX, int mouseY) { + protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { String machineName = fitLabel(title.getString(), width - 8); - font.drawShadow(matrices, machineName, (imageWidth - font.width(machineName)) / 2, 1, 0xFFFFFF); - font.drawShadow(matrices, fitLabel(playerInventoryLabel.getString(), imageWidth - 16), + graphics.drawString(font, machineName, (imageWidth - font.width(machineName)) / 2, 1, 0xFFFFFF); + graphics.drawString(font, fitLabel(playerInventoryLabel.getString(), imageWidth - 16), 8, MACHINE_TOP + MACHINE_HEIGHT, 0xFFFFFF); } @@ -289,29 +289,38 @@ private String fitLabel(String text, int availableWidth) { } @Override - protected void renderBg(PoseStack matrices, float f, int i, int j) { - this.matrices = matrices; + protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { + this.graphics = graphics; RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, playerInventoryBox); int x = (width - imageWidth) / 2; int y = (height - imageHeight) / 2; final int playerInventoryWidth = 176; final int playerInventoryHeight = 90; - this.blit(x, y + PLAYER_PANEL_TOP, 0, 132, playerInventoryWidth, playerInventoryHeight); - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, guiDisplayImage); - this.blit(x, y + MACHINE_TOP, 0, 0, guiWidth, MACHINE_HEIGHT); - drawGUIDecorations(entity, this, x, y + MACHINE_TOP, getZLevel()); - RenderSystem.disableBlend(); + try { + blit(playerInventoryBox, x, y + PLAYER_PANEL_TOP, 0, 132, playerInventoryWidth, playerInventoryHeight); + blit(x, y + MACHINE_TOP, 0, 0, guiWidth, MACHINE_HEIGHT); + drawGUIDecorations(entity, this, x, y + MACHINE_TOP, getZLevel()); + } finally { + this.graphics = null; + RenderSystem.disableBlend(); + } } - /** Retains the decoration API while using the current screen matrix. */ + /** Draws from the machine texture during the decoration callback. */ public void blit(int x, int y, int u, int v, int width, int height) { - super.blit(matrices, x, y, u, v, width, height); + blit(guiDisplayImage, x, y, u, v, width, height); + } + + public void blit(ResourceLocation texture, int x, int y, int u, int v, int width, int height) { + graphics.blit(texture, x, y, u, v, width, height); } - public PoseStack getMatrices() { return matrices; } + /** The active render context, available while drawing decorations. */ + public GuiGraphics getGraphics() { return graphics; } + + public PoseStack getMatrices() { return getGraphics().pose(); } /** * Gets the z-coordinate of this GUI element * @return screen depth coordinate diff --git a/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimpleFluidMachine.java b/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimpleFluidMachine.java index 7c9ae18a..9565785e 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimpleFluidMachine.java +++ b/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimpleFluidMachine.java @@ -634,7 +634,7 @@ public void setItem(int slot, ItemStack item) { if(this.getInventory() == null) return; ItemStack existing = this.getInventory()[slot]; final boolean flag = item != null && !item.isEmpty() && existing != null && !existing.isEmpty() - && item.sameItem(existing) && ItemStack.tagMatches(item, existing); + && ItemStack.isSameItemSameTags(item, existing); this.getInventory()[slot] = (item == null || item.isEmpty()) ? null : item; if (item != null && item.getCount() > this.getMaxStackSize()) { item.setCount(this.getMaxStackSize()); diff --git a/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimplePowerMachine.java b/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimplePowerMachine.java index 8f3d8c41..e78c7d3b 100644 --- a/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimplePowerMachine.java +++ b/src/main/java/cyano/poweradvantage/api/simple/TileEntitySimplePowerMachine.java @@ -622,7 +622,7 @@ public void setItem(int slot, ItemStack item) { if(this.getInventory() == null) return; ItemStack existing = this.getInventory()[slot]; final boolean flag = item != null && !item.isEmpty() && existing != null && !existing.isEmpty() - && item.sameItem(existing) && ItemStack.tagMatches(item, existing); + && ItemStack.isSameItemSameTags(item, existing); this.getInventory()[slot] = (item == null || item.isEmpty()) ? null : item; if (item != null && item.getCount() > this.getMaxStackSize()) { item.setCount(this.getMaxStackSize()); diff --git a/src/main/java/zone/moddev/mc/basepower/PowerAdvantage.java b/src/main/java/zone/moddev/mc/basepower/PowerAdvantage.java index 23b108b5..2607b55e 100644 --- a/src/main/java/zone/moddev/mc/basepower/PowerAdvantage.java +++ b/src/main/java/zone/moddev/mc/basepower/PowerAdvantage.java @@ -42,7 +42,7 @@ public final class PowerAdvantage { public static final String MODID = "basepower"; public static final String NAME = "basePower"; - public static final String VERSION = "2.4.11.119041"; + public static final String VERSION = "2.4.12.120011"; public static final Logger LOGGER = LogManager.getLogger(MODID); private static PowerAdvantage instance; @@ -85,6 +85,7 @@ public PowerAdvantage() { zone.moddev.mc.basepower.recipe.MaterialTags::registerPack); Fluids.init(); + ItemGroups.register(FMLJavaModLoadingContext.get().getModEventBus()); migrateLegacyOreSpawnConfiguration(); migrateLegacyConfiguration(); diff --git a/src/main/java/zone/moddev/mc/basepower/blocks/BlockFrame.java b/src/main/java/zone/moddev/mc/basepower/blocks/BlockFrame.java index a35eb137..a75471ad 100644 --- a/src/main/java/zone/moddev/mc/basepower/blocks/BlockFrame.java +++ b/src/main/java/zone/moddev/mc/basepower/blocks/BlockFrame.java @@ -2,7 +2,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.entity.player.Player; import net.minecraft.core.BlockPos; @@ -19,9 +18,8 @@ */ public class BlockFrame extends Block { - public BlockFrame(Material material, float hardness, float resistance) { - super(Block.Properties.of(material).sound(SoundType.METAL) - .strength(hardness, resistance).noOcclusion().dynamicShape()); + public BlockFrame(Properties properties) { + super(properties.sound(SoundType.METAL).noOcclusion().dynamicShape()); } public boolean isFullCube(BlockState bs) { diff --git a/src/main/java/zone/moddev/mc/basepower/blocks/BlockPowerSwitch.java b/src/main/java/zone/moddev/mc/basepower/blocks/BlockPowerSwitch.java index 139c7428..389764ce 100644 --- a/src/main/java/zone/moddev/mc/basepower/blocks/BlockPowerSwitch.java +++ b/src/main/java/zone/moddev/mc/basepower/blocks/BlockPowerSwitch.java @@ -5,7 +5,8 @@ import cyano.poweradvantage.api.PowerConnectorContext; import zone.moddev.mc.basepower.conduitnetwork.ConduitRegistry; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; +import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.BlockState; @@ -31,11 +32,10 @@ public class BlockPowerSwitch extends Block implements ITypedConduit { * Constructor for making a power switch * * @param powerType Type of power to switch - * @param blockMaterial The block material (usually piston material) - * @param blockHardness The hardness of the block (0.75 is a good value) + * @param properties Block behavior, including break hardness */ - public BlockPowerSwitch(ConduitType powerType, Material blockMaterial, float blockHardness) { - super(Block.Properties.of(blockMaterial).strength(blockHardness)); + public BlockPowerSwitch(ConduitType powerType, Block.Properties properties) { + super(properties); this.powerType = new ConduitType[1]; this.powerType[0] = powerType; this.registerDefaultState(defaultBlockState().setValue(ACTIVE, false)); @@ -47,7 +47,8 @@ public BlockPowerSwitch(ConduitType powerType, Material blockMaterial, float blo * @param powerType Type of power to switch */ public BlockPowerSwitch(ConduitType powerType) { - this(powerType, Material.PISTON, 0.75f); + this(powerType, Properties.of().mapColor(MapColor.STONE).pushReaction(PushReaction.BLOCK) + .forceSolidOn().strength(0.75F)); } /** diff --git a/src/main/java/zone/moddev/mc/basepower/gui/FilteredFluidTankGUI.java b/src/main/java/zone/moddev/mc/basepower/gui/FilteredFluidTankGUI.java index 6ba10f8f..6bdc640e 100644 --- a/src/main/java/zone/moddev/mc/basepower/gui/FilteredFluidTankGUI.java +++ b/src/main/java/zone/moddev/mc/basepower/gui/FilteredFluidTankGUI.java @@ -3,7 +3,6 @@ import cyano.poweradvantage.api.fluid.FluidPoweredEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; import zone.moddev.mc.basepower.math.Integer2D; -import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.resources.ResourceLocation; import cyano.poweradvantage.api.fluid.FluidStack; @@ -27,8 +26,6 @@ public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int guiDisplayImage, guiContainer, x, y, z); } } - com.mojang.blaze3d.systems.RenderSystem.setShaderColor(1f, 1f, 1f, 1f); // reset tint - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, guiDisplayImage); guiContainer.blit(x + 77, y + 6, 176, 0, 22, 66); // x, y, textureOffsetX, textureOffsetY, width, height) } @@ -37,16 +34,6 @@ public static void drawFluidBar( FluidStack fs, float barHeight, int xPos, int yPos, ResourceLocation displayImage, GUIContainer guiContainer, int x, int y, float zLevel ) { - barHeight = Float.isFinite(barHeight) ? Math.max(0F, Math.min(1F, barHeight)) : 0F; - final int w = 16; - final int barSlotHeight = 60; - final int h = (int) (barSlotHeight * barHeight); - - - FluidTankGUI.drawFluidFilledRectangle(guiContainer, fs, x + xPos, y + yPos + barSlotHeight - h, w, h, zLevel); - //guiContainer.drawModalRectWithCustomSizedTexture(x+xPos, y+yPos+barSlotHeight-h, 0, 0, w, h, 16, h);//h * texPerPixel); // x, y, u, v, width, height, textureWidth, textureHeight - - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, displayImage); - guiContainer.blit(x + xPos - 3, y + yPos - 3, 176, 0, 22, 66); // x, y, textureOffsetX, textureOffsetY, width, height) + FluidTankGUI.drawFluidBar(fs, barHeight, xPos, yPos, displayImage, guiContainer, x, y, zLevel); } } diff --git a/src/main/java/zone/moddev/mc/basepower/gui/FluidTankGUI.java b/src/main/java/zone/moddev/mc/basepower/gui/FluidTankGUI.java index c42ca9b6..e5e9d6f6 100644 --- a/src/main/java/zone/moddev/mc/basepower/gui/FluidTankGUI.java +++ b/src/main/java/zone/moddev/mc/basepower/gui/FluidTankGUI.java @@ -3,7 +3,7 @@ import cyano.poweradvantage.api.fluid.FluidPoweredEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; import zone.moddev.mc.basepower.math.Integer2D; -import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.BufferBuilder; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -35,8 +35,6 @@ public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int guiDisplayImage, guiContainer, x, y, z); } } - com.mojang.blaze3d.systems.RenderSystem.setShaderColor(1f, 1f, 1f, 1f); // reset tint - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, guiDisplayImage); guiContainer.blit(x + 77, y + 6, 176, 0, 22, 66); // x, y, textureOffsetX, textureOffsetY, width, height) } @@ -51,10 +49,7 @@ public static void drawFluidBar( final int h = (int) (barSlotHeight * barHeight); FluidTankGUI.drawFluidFilledRectangle(guiContainer, fs, x + xPos, y + yPos + barSlotHeight - h, w, h, zLevel); - //guiContainer.drawModalRectWithCustomSizedTexture(x+xPos, y+yPos+barSlotHeight-h, 0, 0, w, h, 16, h);//h * texPerPixel); // x, y, u, v, width, height, textureWidth, textureHeight - - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, displayImage); - guiContainer.blit(x + xPos - 3, y + yPos - 3, 176, 0, 22, 66); // x, y, textureOffsetX, textureOffsetY, width, height) + guiContainer.blit(displayImage, x + xPos - 3, y + yPos - 3, 176, 0, 22, 66); } @@ -71,7 +66,6 @@ public static void drawFluidFilledRectangle( if (stillTexture == null) return; TextureAtlasSprite sprite = guiContainer.getMinecraft().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS) .apply(stillTexture); - com.mojang.blaze3d.systems.RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); int color = rendering.getTintColor(fluidStack); if (fs.getFluid().isSame(net.minecraft.world.level.material.Fluids.WATER)) { color = guiContainer.getMinecraft().level != null && guiContainer.getMinecraft().player != null @@ -80,9 +74,12 @@ public static void drawFluidFilledRectangle( float red = ((color >>> 16) & 255) / 255F; float green = ((color >>> 8) & 255) / 255F; float blue = (color & 255) / 255F; + guiContainer.getGraphics().flush(); + var pose = guiContainer.getMatrices().last().pose(); + RenderSystem.setShaderTexture(0, sprite.atlasLocation()); Tesselator tessellator = Tesselator.getInstance(); BufferBuilder vertexbuffer = tessellator.getBuilder(); - com.mojang.blaze3d.systems.RenderSystem.setShader(net.minecraft.client.renderer.GameRenderer::getPositionTexColorShader); + RenderSystem.setShader(net.minecraft.client.renderer.GameRenderer::getPositionTexColorShader); vertexbuffer.begin(com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); for (int dy = 0; dy < height; dy += 16) { int tileHeight = Math.min(16, height - dy); @@ -90,10 +87,10 @@ public static void drawFluidFilledRectangle( int tileWidth = Math.min(16, width - dx); float u0 = sprite.getU0(), u1 = sprite.getU(tileWidth); float v0 = sprite.getV0(), v1 = sprite.getV(tileHeight); - vertexbuffer.vertex(x + dx, y + dy + tileHeight, zLevel).uv(u0, v1).color(red, green, blue, 1F).endVertex(); - vertexbuffer.vertex(x + dx + tileWidth, y + dy + tileHeight, zLevel).uv(u1, v1).color(red, green, blue, 1F).endVertex(); - vertexbuffer.vertex(x + dx + tileWidth, y + dy, zLevel).uv(u1, v0).color(red, green, blue, 1F).endVertex(); - vertexbuffer.vertex(x + dx, y + dy, zLevel).uv(u0, v0).color(red, green, blue, 1F).endVertex(); + vertexbuffer.vertex(pose, x + dx, y + dy + tileHeight, zLevel).uv(u0, v1).color(red, green, blue, 1F).endVertex(); + vertexbuffer.vertex(pose, x + dx + tileWidth, y + dy + tileHeight, zLevel).uv(u1, v1).color(red, green, blue, 1F).endVertex(); + vertexbuffer.vertex(pose, x + dx + tileWidth, y + dy, zLevel).uv(u1, v0).color(red, green, blue, 1F).endVertex(); + vertexbuffer.vertex(pose, x + dx, y + dy, zLevel).uv(u0, v0).color(red, green, blue, 1F).endVertex(); } } tessellator.end(); diff --git a/src/main/java/zone/moddev/mc/basepower/init/Blocks.java b/src/main/java/zone/moddev/mc/basepower/init/Blocks.java index 2a749a94..6eac06c8 100644 --- a/src/main/java/zone/moddev/mc/basepower/init/Blocks.java +++ b/src/main/java/zone/moddev/mc/basepower/init/Blocks.java @@ -9,7 +9,9 @@ import cyano.poweradvantage.api.fluid.InteractiveFluidBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.block.SoundType; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.item.Item; import net.minecraft.world.item.BlockItem; @@ -87,10 +89,11 @@ public static synchronized void init() { fluid_pipe = add(new FluidPipeBlock(), "fluid_pipe"); fluid_pipe_terminal = add(new TerminalFluidPipeBlock(), "fluid_pipe_terminal"); fluid_switch = add(new BlockPowerSwitch(Fluids.fluidConduit_general), "fluid_switch"); - steel_frame = add(new BlockFrame(Material.PISTON, 0.75F, STEEL_BLAST_RESISTANCE), "steel_frame"); + steel_frame = add(new BlockFrame(GUIBlock.machineProperties(0.75F) + .strength(0.75F, STEEL_BLAST_RESISTANCE)), "steel_frame"); final float hardness = 0.75F; - item_conveyor = (GUIBlock) add(new BlockConveyor(Material.PISTON, hardness), "item_conveyor"); + item_conveyor = (GUIBlock) add(new BlockConveyor(hardness), "item_conveyor"); item_filter_block = filter("item_filter_block", TileEntityBlockFilter.class, hardness); item_filter_food = filter("item_filter_food", TileEntityFoodFilter.class, hardness); item_filter_fuel = filter("item_filter_fuel", TileEntityFuelFilter.class, hardness); @@ -104,13 +107,11 @@ public static synchronized void init() { infinite_electricity = (GUIBlock) add(new InfiniteEnergyBlock(new ConduitType("electricity")), "infinite_electricity"); infinite_quantum = (GUIBlock) add(new InfiniteEnergyBlock(new ConduitType("quantum")), "infinite_quantum"); - Block.Properties oilProperties = Block.Properties.of(Material.WATER).noCollission() - .strength(100.0F).dynamicShape(); refined_oil_block = (LiquidBlock) add(new InteractiveFluidBlock(() -> Fluids.refined_oil, - oilProperties, true, (world, entity) -> entity .addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200))), + oilProperties(), true, (world, entity) -> entity.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200))), "refined_oil"); crude_oil_block = (LiquidBlock) add(new InteractiveFluidBlock(() -> Fluids.crude_oil, - oilProperties, true, (world, entity) -> entity .addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 200, 2))), + oilProperties(), true, (world, entity) -> entity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 200, 2))), "crude_oil"); ModSupport.initBlocks(); @@ -119,7 +120,12 @@ public static synchronized void init() { private static GUIBlock filter(String id, Class type, float hardness) { - return (GUIBlock) add(new BlockConveyorFilter(Material.PISTON, hardness, type), id); + return (GUIBlock) add(new BlockConveyorFilter(hardness, type), id); + } + + private static Block.Properties oilProperties() { + return Block.Properties.of().mapColor(MapColor.WATER).replaceable().liquid().noCollission() + .strength(100.0F).dynamicShape().pushReaction(PushReaction.DESTROY).noLootTable().sound(SoundType.EMPTY); } public static Block add(Block block, String id) { diff --git a/src/main/java/zone/moddev/mc/basepower/init/ItemGroups.java b/src/main/java/zone/moddev/mc/basepower/init/ItemGroups.java index 8cb066ea..74d52557 100644 --- a/src/main/java/zone/moddev/mc/basepower/init/ItemGroups.java +++ b/src/main/java/zone/moddev/mc/basepower/init/ItemGroups.java @@ -4,22 +4,34 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.BlockItem; -import net.minecraftforge.event.CreativeModeTabEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import zone.moddev.mc.basepower.PowerAdvantage; -@Mod.EventBusSubscriber(modid = PowerAdvantage.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) public final class ItemGroups { public static CreativeModeTab tab_powerAdvantage; private static final Set VISIBLE_ITEMS = ConcurrentHashMap.newKeySet(); + private static final DeferredRegister TABS = + DeferredRegister.create(Registries.CREATIVE_MODE_TAB, PowerAdvantage.MODID); + + static { + TABS.register("machines", () -> tab_powerAdvantage = CreativeModeTab.builder() + .title(Component.translatable("itemGroup." + PowerAdvantage.MODID)) + .icon(() -> Items.sprocket.getDefaultInstance()) + .displayItems((parameters, output) -> VISIBLE_ITEMS.stream() + .sorted(Comparator.comparing(ItemGroups::category, String.CASE_INSENSITIVE_ORDER) + .thenComparing(ForgeRegistries.ITEMS::getKey)) + .forEach(output::accept)) + .build()); + } + private ItemGroups() {} @@ -29,15 +41,8 @@ public static T show(T item) { return item; } - @SubscribeEvent - public static void register(CreativeModeTabEvent.Register event) { - tab_powerAdvantage = event.registerCreativeModeTab(new ResourceLocation(PowerAdvantage.MODID, "machines"), - builder -> builder.title(Component.translatable("itemGroup." + PowerAdvantage.MODID)) - .icon(() -> Items.sprocket.getDefaultInstance()) - .displayItems((parameters, output) -> VISIBLE_ITEMS.stream() - .sorted(Comparator.comparing(ItemGroups::category, String.CASE_INSENSITIVE_ORDER) - .thenComparing(ForgeRegistries.ITEMS::getKey)) - .forEach(output::accept))); + public static void register(IEventBus bus) { + TABS.register(bus); } private static String category(Item item) { diff --git a/src/main/java/zone/moddev/mc/basepower/init/ModSupport.java b/src/main/java/zone/moddev/mc/basepower/init/ModSupport.java index d5cb1193..8036a17c 100644 --- a/src/main/java/zone/moddev/mc/basepower/init/ModSupport.java +++ b/src/main/java/zone/moddev/mc/basepower/init/ModSupport.java @@ -10,7 +10,7 @@ import cyano.poweradvantage.api.modsupport.techreborn.BlockTRConverter; import cyano.poweradvantage.api.modsupport.techreborn.TileEntityTRElectricityConverter; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Material; +import cyano.poweradvantage.api.GUIBlock; import zone.moddev.mc.basepower.PowerAdvantage; import zone.moddev.mc.basepower.config.PowerAdvantageConfig; @@ -28,14 +28,13 @@ private ModSupport() {} public static synchronized void initBlocks() { if (initialized) return; float hardness = 0.75F; - Material material = Material.PISTON; - converter_rf_steam = Blocks.add(new BlockRFConverter(material, hardness, new ConduitType("steam"), + converter_rf_steam = Blocks.add(new BlockRFConverter(GUIBlock.machineProperties(hardness), new ConduitType("steam"), TileEntityRFSteamConverter.class), "converter_rf_steam"); - converter_rf_electricity = Blocks.add(new BlockRFConverter(material, hardness, new ConduitType("electricity"), + converter_rf_electricity = Blocks.add(new BlockRFConverter(GUIBlock.machineProperties(hardness), new ConduitType("electricity"), TileEntityRFElectricityConverter.class), "converter_rf_electricity"); - converter_rf_quantum = Blocks.add(new BlockRFConverter(material, hardness, new ConduitType("quantum"), + converter_rf_quantum = Blocks.add(new BlockRFConverter(GUIBlock.machineProperties(hardness), new ConduitType("quantum"), TileEntityRFQuantumConverter.class), "converter_rf_quantum"); - converter_tr_electricity = Blocks.add(new BlockTRConverter(material, hardness, new ConduitType("electricity"), + converter_tr_electricity = Blocks.add(new BlockTRConverter(GUIBlock.machineProperties(hardness), new ConduitType("electricity"), TileEntityTRElectricityConverter.class), "converter_tr_electricity"); initialized = true; } diff --git a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyor.java b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyor.java index 57556588..6fafbdd1 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyor.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyor.java @@ -3,7 +3,6 @@ import cyano.poweradvantage.api.GUIBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.state.properties.DirectionProperty; @@ -21,9 +20,8 @@ public class BlockConveyor extends GUIBlock { public static final DirectionProperty FACING = BlockStateProperties.FACING; - public BlockConveyor(Material material, float hardness) { - super(Block.Properties.of(material).strength(hardness) - .sound(SoundType.METAL).noOcclusion().dynamicShape()); + public BlockConveyor(float hardness) { + super(machineProperties(hardness).sound(SoundType.METAL)); registerDefaultState(getStateDefinition().any().setValue(FACING, Direction.NORTH)); } diff --git a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyorFilter.java b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyorFilter.java index 8d889506..63fb0204 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyorFilter.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/BlockConveyorFilter.java @@ -4,7 +4,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.HorizontalDirectionalBlock; import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.state.properties.DirectionProperty; @@ -23,10 +22,9 @@ public class BlockConveyorFilter extends GUIBlock { public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; private final Class tileEntityClass; - public BlockConveyorFilter(Material material, float hardness, + public BlockConveyorFilter(float hardness, Class tileEntityClass) { - super(Block.Properties.of(material).strength(hardness) - .sound(SoundType.METAL).noOcclusion().dynamicShape()); + super(machineProperties(hardness).sound(SoundType.METAL)); this.tileEntityClass = tileEntityClass; registerDefaultState(getStateDefinition().any().setValue(FACING, Direction.NORTH)); } diff --git a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyor.java b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyor.java index 651a0574..fe6f5a84 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyor.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyor.java @@ -159,7 +159,7 @@ protected static boolean canInsertItemInto(ItemStack item, WorldlyContainer dest ItemStack destItem = dest.getItem(slot); if(destItem == null || destItem.isEmpty()) { return true; - } else if (ItemStack.isSame(item, destItem) && ItemStack.tagMatches(item, destItem) + } else if (ItemStack.isSameItemSameTags(item, destItem) && destItem.getCount() < Math.min(dest.getMaxStackSize(), destItem.getMaxStackSize())) { return true; } @@ -183,8 +183,7 @@ protected static boolean transferItem(WorldlyContainer src, Direction srcFace, W if(dest.canPlaceItemThroughFace(destValidSlots[j], item, destFace)){ ItemStack otherItem = dest.getItem(destValidSlots[j]); if(otherItem != null && !otherItem.isEmpty() - && ItemStack.isSame(item, otherItem) - && ItemStack.tagMatches(item, otherItem) + && ItemStack.isSameItemSameTags(item, otherItem) && otherItem.getCount() < dest.getMaxStackSize() && otherItem.getCount() < otherItem.getMaxStackSize()){ src.removeItem(srcValidSlots[i], 1); @@ -395,7 +394,7 @@ public void setField(int arg0, int arg1) { public void setItem(int slot, ItemStack item) { ItemStack existing = this.getInventory()[slot]; final boolean flag = item != null && !item.isEmpty() && existing != null && !existing.isEmpty() - && item.sameItem(existing) && ItemStack.tagMatches(item, existing); + && ItemStack.isSameItemSameTags(item, existing); this.getInventory()[slot] = (item == null || item.isEmpty()) ? null : item; if (item != null && item.getCount() > this.getMaxStackSize()) { item.setCount(this.getMaxStackSize()); diff --git a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyorFilter.java b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyorFilter.java index c9f7a13f..48da26d1 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyorFilter.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityConveyorFilter.java @@ -89,7 +89,7 @@ protected boolean isValidItemFor(ItemStack item, BlockEntity target, Direction s private void dropItem(BlockEntity target) { Level w = getLevel(); BlockState bs = w.getBlockState(getBlockPos().below()); - if (target == null && !(bs.getMaterial().blocksMotion())) { + if (target == null && !bs.blocksMotion()) { // drop item in the air ItemEntity ie = new ItemEntity(w, getBlockPos().getX() + 0.5, getBlockPos().getY() - 0.5, getBlockPos().getZ() + 0.5, getInventory()[0]); ie.setDeltaMovement(0, 0, 0); diff --git a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityInventoryFilter.java b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityInventoryFilter.java index 04e4fefa..bb5e5617 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityInventoryFilter.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/conveyors/TileEntityInventoryFilter.java @@ -16,7 +16,7 @@ public TileEntityInventoryFilter(net.minecraft.core.BlockPos pos, net.minecraft. public boolean matchesFilter(ItemStack item) { if (item == null) return false; for (int i = 1; i < this.getInventory().length; i++) { - if (this.getInventory()[i] != null && ItemStack.isSame(this.getInventory()[i], item)) { + if (this.getInventory()[i] != null && ItemStack.isSameItem(this.getInventory()[i], item)) { return true; } } diff --git a/src/main/java/zone/moddev/mc/basepower/machines/creative/InfiniteEnergyBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/creative/InfiniteEnergyBlock.java index 72c8e587..704ad988 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/creative/InfiniteEnergyBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/creative/InfiniteEnergyBlock.java @@ -3,7 +3,7 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.PoweredEntity; import cyano.poweradvantage.api.simple.BlockSimplePowerMachine; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; @@ -12,7 +12,8 @@ public class InfiniteEnergyBlock extends BlockSimplePowerMachine { public InfiniteEnergyBlock(ConduitType energyType) { - super(Material.METAL, 0.75f, energyType); + super(Properties.of().mapColor(MapColor.METAL).forceSolidOn().strength(0.75F) + .noOcclusion().dynamicShape(), energyType); } @Override diff --git a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDischargeBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDischargeBlock.java index 896d75f0..fb806adf 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDischargeBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDischargeBlock.java @@ -4,7 +4,6 @@ import cyano.poweradvantage.api.PoweredEntity; import cyano.poweradvantage.api.simple.BlockSimpleFluidMachine; import cyano.poweradvantage.api.simple.TileEntitySimplePowerMachine; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.Container; import net.minecraft.world.Containers; @@ -16,7 +15,7 @@ public class FluidDischargeBlock extends BlockSimpleFluidMachine { public FluidDischargeBlock() { - super(Material.PISTON, 3f); + super(machineProperties(3F)); } @Override diff --git a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDrainBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDrainBlock.java index 5126a826..baff050c 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDrainBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidDrainBlock.java @@ -3,7 +3,6 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.PoweredEntity; import cyano.poweradvantage.api.simple.BlockSimpleFluidMachine; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.core.BlockPos; @@ -14,7 +13,7 @@ public class FluidDrainBlock extends BlockSimpleFluidMachine { public FluidDrainBlock() { - super(Material.PISTON, 3f); + super(machineProperties(3F)); } @Override diff --git a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidPipeBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidPipeBlock.java index 5238ea81..ecba2974 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidPipeBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/FluidPipeBlock.java @@ -4,7 +4,8 @@ import zone.moddev.mc.basepower.init.Blocks; import zone.moddev.mc.basepower.util.FluidHandlerHelper; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; +import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; @@ -17,7 +18,8 @@ public class FluidPipeBlock extends BlockSimpleFluidConduit { public FluidPipeBlock() { - super(Material.PISTON, 0.75f, 4f / 16f); + super(Properties.of().mapColor(MapColor.STONE).pushReaction(PushReaction.BLOCK) + .forceSolidOn().strength(0.75F), 4F / 16F); } diff --git a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/MetalTankBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/MetalTankBlock.java index 0f4a5a69..0b5e3673 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/MetalTankBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/MetalTankBlock.java @@ -3,7 +3,6 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.PoweredEntity; import cyano.poweradvantage.api.simple.BlockSimpleFluidMachine; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.core.BlockPos; @@ -13,7 +12,7 @@ public class MetalTankBlock extends BlockSimpleFluidMachine { public MetalTankBlock() { - super(Material.PISTON, 3f); + super(machineProperties(3F)); } @Override diff --git a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StillBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StillBlock.java index c8e0b855..f45cd7e0 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StillBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StillBlock.java @@ -3,7 +3,8 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.PoweredEntity; import cyano.poweradvantage.api.simple.BlockSimpleFluidMachine; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; +import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.BlockState; @@ -23,8 +24,8 @@ public class StillBlock extends BlockSimpleFluidMachine { public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); public StillBlock() { - super(net.minecraft.world.level.block.Block.Properties.of(Material.PISTON) - .strength(3f).lightLevel(state -> state.getValue(ACTIVE) ? 12 : 0)); + super(Properties.of().mapColor(MapColor.STONE).pushReaction(PushReaction.BLOCK).forceSolidOn() + .strength(3F).lightLevel(state -> state.getValue(ACTIVE) ? 12 : 0)); this.registerDefaultState(defaultBlockState().setValue(ACTIVE, false)); } diff --git a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StorageTankBlock.java b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StorageTankBlock.java index ea1473a0..b379b0d0 100644 --- a/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StorageTankBlock.java +++ b/src/main/java/zone/moddev/mc/basepower/machines/fluidmachines/StorageTankBlock.java @@ -9,7 +9,6 @@ import cyano.poweradvantage.api.fluid.FluidStack; import cyano.poweradvantage.api.fluid.FluidTank; import cyano.poweradvantage.api.simple.BlockSimpleFluidMachine; -import net.minecraft.world.level.material.Material; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; @@ -26,7 +25,7 @@ /** Portable tank block. FluidID and Volume remain unchanged for old item stacks. */ public class StorageTankBlock extends BlockSimpleFluidMachine { - public StorageTankBlock() { super(Material.PISTON, 3F); } + public StorageTankBlock() { super(machineProperties(3F)); } @Override public PoweredEntity newBlockEntity(net.minecraft.core.BlockPos pos, net.minecraft.world.level.block.state.BlockState state) { return new StorageTankTileEntity(pos, state); } @Override public boolean hasAnalogOutputSignal(BlockState state) { return true; } diff --git a/src/main/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemaps.java b/src/main/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemaps.java index be4fd5fe..756e1036 100644 --- a/src/main/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemaps.java +++ b/src/main/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemaps.java @@ -157,6 +157,15 @@ static ResourceLocation replacement(ResourceLocation registry, ResourceLocation target = "zombified_piglin"; } else if (registry.equals(new ResourceLocation("minecraft:item")) && old.getPath().equals("zombie_pigman_spawn_egg")) { target = "zombified_piglin_spawn_egg"; + } else if (registry.equals(new ResourceLocation("minecraft:item"))) { + // Forge keeps the 1.19.4 experimental IDs even when that data pack was not enabled. + target = switch (old.getPath()) { + case "pottery_shard_archer" -> "archer_pottery_sherd"; + case "pottery_shard_arms_up" -> "arms_up_pottery_sherd"; + case "pottery_shard_prize" -> "prize_pottery_sherd"; + case "pottery_shard_skull" -> "skull_pottery_sherd"; + default -> null; + }; } else if (registry.equals(new ResourceLocation("minecraft:worldgen/biome")) && old.getPath().equals("nether")) { target = "nether_wastes"; } else if (registry.equals(new ResourceLocation("minecraft:sound_event"))) { @@ -166,6 +175,10 @@ static ResourceLocation replacement(ResourceLocation registry, ResourceLocation // The former single Nether biome becomes Nether Wastes in 1.16. if (old.getPath().equals("music.nether")) target = "music.nether.nether_wastes"; if (old.getPath().equals("item.sweet_berries.pick_from_bush")) target = "block.sweet_berry_bush.pick_berries"; + if (old.getPath().equals("item.brush.brushing")) target = "item.brush.brushing.generic"; + if (old.getPath().equals("item.brush.brush_sand_completed")) target = "item.brush.brushing.sand.complete"; + // Native biomes choose their own new music; this alias is for the old shared registry ID. + if (old.getPath().equals("music.overworld.jungle_and_forest")) target = "music.overworld.forest"; } return target == null ? null : new ResourceLocation("minecraft", target); } diff --git a/src/main/java/zone/moddev/mc/basepower/registry/MachineGUIRegistry.java b/src/main/java/zone/moddev/mc/basepower/registry/MachineGUIRegistry.java index b693e161..675ce26d 100644 --- a/src/main/java/zone/moddev/mc/basepower/registry/MachineGUIRegistry.java +++ b/src/main/java/zone/moddev/mc/basepower/registry/MachineGUIRegistry.java @@ -61,7 +61,7 @@ public static void registerTypes(RegisterEvent event) { private static SimpleMachineGUI.Container createClientContainer( int windowId, Inventory inventory, FriendlyByteBuf data) { BlockPos pos = data.readBlockPos(); - Level world = inventory.player.level; + Level world = inventory.player.level(); BlockEntity tile = world.getBlockEntity(pos); Block block = world.getBlockState(pos).getBlock(); if (!(block instanceof GUIBlock) || !(tile instanceof Container)) { @@ -87,7 +87,7 @@ public static void registerScreens() { public static void open(ServerPlayer player, Level world, BlockPos pos, int id) { BlockEntity tile = world.getBlockEntity(pos); - if (world.isClientSide || player.level != world || !(tile instanceof Container)) return; + if (world.isClientSide || player.level() != world || !(tile instanceof Container)) return; SimpleMachineGUI gui = definition(id); NetworkHooks.openScreen(player, new MenuProvider() { @Override public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player owner) { diff --git a/src/main/java/zone/moddev/mc/basepower/util/FluidContainerHelper.java b/src/main/java/zone/moddev/mc/basepower/util/FluidContainerHelper.java index 5c9360b8..5a3e54b2 100644 --- a/src/main/java/zone/moddev/mc/basepower/util/FluidContainerHelper.java +++ b/src/main/java/zone/moddev/mc/basepower/util/FluidContainerHelper.java @@ -18,7 +18,7 @@ private FluidContainerHelper() {} public static boolean interact(Player player, InteractionHand hand, IAdvantageFluidHandler handler, Direction face) { - if (player.level.isClientSide) return false; + if (player.level().isClientSide) return false; return net.minecraftforge.fluids.FluidUtil.interactWithFluidHandler(player, hand, new ForgeFluidAdapter(handler, face, () -> { if (handler instanceof net.minecraft.world.level.block.entity.BlockEntity) diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 410e4c28..5756dc9f 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -14,14 +14,14 @@ description='''API and shared machines for pressure, electricity, quantum power, [[dependencies.basepower]] modId="basemetals" mandatory=false -versionRange="[3.1.2.119041,4.0.0)" +versionRange="[3.1.2.120011,4.0.0)" ordering="AFTER" side="BOTH" [[dependencies.basepower]] modId="orespawn" mandatory=true -versionRange="[4.1.0.119041,5.0.0)" +versionRange="[4.1.0.120011,5.0.0)" ordering="AFTER" side="BOTH" diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index fbf929c9..6b0927b0 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,8 +1,8 @@ { "pack": { "description": "Power Advantage resources", - "pack_format": 12, - "forge:resource_pack_format": 13, - "forge:data_pack_format": 12 + "pack_format": 15, + "forge:resource_pack_format": 15, + "forge:data_pack_format": 15 } } diff --git a/src/test/java/zone/moddev/mc/basepower/migration/LegacyForgeAttributeRegistryTest.java b/src/test/java/zone/moddev/mc/basepower/migration/LegacyForgeAttributeRegistryTest.java index 662ade61..07bf1889 100644 --- a/src/test/java/zone/moddev/mc/basepower/migration/LegacyForgeAttributeRegistryTest.java +++ b/src/test/java/zone/moddev/mc/basepower/migration/LegacyForgeAttributeRegistryTest.java @@ -100,9 +100,9 @@ static void registerForgeAttributes() throws ReflectiveOperationException { DataFixTypes.PLAYER, source, 1343); CompoundTag value = actual.getList("Attributes", 10).getCompound(0); assertEquals("forge:reach_distance", value.getString("Name")); - assertSame(ForgeMod.REACH_DISTANCE.get(), ForgeRegistries.ATTRIBUTES.getValue( + assertSame(ForgeMod.BLOCK_REACH.get(), ForgeRegistries.ATTRIBUTES.getValue( new net.minecraft.resources.ResourceLocation(value.getString("Name")))); - AttributeInstance nativeAttribute = new AttributeInstance(ForgeMod.REACH_DISTANCE.get(), unused -> {}); + AttributeInstance nativeAttribute = new AttributeInstance(ForgeMod.BLOCK_REACH.get(), unused -> {}); nativeAttribute.load(value); assertEquals(7.5D, nativeAttribute.getBaseValue(), 0D); assertEquals(7.625D, nativeAttribute.getValue(), 0D); diff --git a/src/test/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemapsTest.java b/src/test/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemapsTest.java index c2dfdc79..ed49356b 100644 --- a/src/test/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemapsTest.java +++ b/src/test/java/zone/moddev/mc/basepower/migration/VanillaRegistryRemapsTest.java @@ -3,6 +3,8 @@ import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; import net.minecraft.SharedConstants; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.datafix.DataFixers; import net.minecraft.util.datafix.fixes.References; @@ -20,6 +22,35 @@ public class VanillaRegistryRemapsTest { expect("sound_event", "item.sweet_berries.pick_from_bush", "block.sweet_berry_bush.pick_berries"); assertNull(VanillaRegistryRemaps.replacement(id("item"), id("item.sweet_berries.pick_from_bush"))); } + + @Test public void preservesTheFourPotteryStacksThroughVanillaAndForgeRenames() { + SharedConstants.tryDetectVersion(); + for (String pattern : new String[]{"archer", "arms_up", "prize", "skull"}) { + String oldName = "pottery_shard_" + pattern; + String newName = pattern + "_pottery_sherd"; + expect("item", oldName, newName); + assertNull(VanillaRegistryRemaps.replacement(id("block"), id(oldName))); + CompoundTag stack = new CompoundTag(); + stack.putString("id", id(oldName).toString()); + stack.putByte("Count", (byte) 7); + CompoundTag metadata = new CompoundTag(); + metadata.putInt("WorksWitness", 1194); + stack.put("tag", metadata); + var fixed = DataFixers.getDataFixer().update(References.ITEM_STACK, + new Dynamic<>(NbtOps.INSTANCE, stack), 3337, 3465); + assertEquals(id(newName).toString(), fixed.get("id").asString().result().orElseThrow()); + assertEquals(7, fixed.get("Count").asInt(-1)); + assertEquals(1194, fixed.get("tag").get("WorksWitness").asInt(-1)); + } + } + + @Test public void retainsExactArchaeologyAndMusicSoundRegistryAliases() { + expect("sound_event", "item.brush.brushing", "item.brush.brushing.generic"); + expect("sound_event", "item.brush.brush_sand_completed", "item.brush.brushing.sand.complete"); + expect("sound_event", "music.overworld.jungle_and_forest", "music.overworld.forest"); + assertNull(VanillaRegistryRemaps.replacement(id("sound_event"), id("item.brush.unknown"))); + assertNull(VanillaRegistryRemaps.replacement(id("item"), id("music.overworld.jungle_and_forest"))); + } @Test public void retainsTheRenamedPigmanEntity() { expect("entity_type", "zombie_pigman", "zombified_piglin"); } diff --git a/src/test/java/zone/moddev/mc/basepower/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/basepower/resources/BuildWorkflowContractTest.java index 3e0365a0..ea1f864b 100644 --- a/src/test/java/zone/moddev/mc/basepower/resources/BuildWorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/basepower/resources/BuildWorkflowContractTest.java @@ -37,11 +37,14 @@ public class BuildWorkflowContractTest { StandardCharsets.UTF_8); int policy = workflow.indexOf("run: git config --global core.autocrlf false"); int checkout = workflow.indexOf("- name: Check out pinned Base Metals"); - assertTrue(name, policy >= 0 && checkout > policy); - assertTrue(name, workflow.contains("ref: " + pins.getProperty("basemetals_source_commit"))); + int oreSpawn = workflow.indexOf("- name: Check out pinned OreSpawn"); + int pinGate = workflow.indexOf("run: bash .github/verify-base-metals-pin.sh"); + assertTrue(name, policy >= 0 && checkout > policy && oreSpawn > policy); + assertTrue(name, pinGate >= 0 && checkout > pinGate); + assertTrue(name, workflow.contains("ref: ${{ steps.base-metals-pin.outputs.commit }}")); assertTrue(name, workflow.contains("BaseMetals-" + pins.getProperty("basemetals_version") + "-deobf.jar")); - assertTrue(name, workflow.contains("ref: 444d86ef48db2bf54422901b067c51d5832197fc")); - assertTrue(name, workflow.contains("master-1.19.4")); + assertTrue(name, workflow.contains("ref: " + pins.getProperty("orespawn_source_commit"))); + assertTrue(name, workflow.contains("master-" + pins.getProperty("minecraft_version"))); assertTrue(name, workflow.contains("java-version: '25.0.3+9.0.LTS'")); assertTrue(name, workflow.contains("java-version: '17.0.1+12'")); assertTrue(name, workflow.contains("java-version: '8.0.502+7'")); diff --git a/src/test/java/zone/moddev/mc/basepower/resources/CreativeTabInitializationTest.java b/src/test/java/zone/moddev/mc/basepower/resources/CreativeTabInitializationTest.java index d97b99e3..2d62be5a 100644 --- a/src/test/java/zone/moddev/mc/basepower/resources/CreativeTabInitializationTest.java +++ b/src/test/java/zone/moddev/mc/basepower/resources/CreativeTabInitializationTest.java @@ -2,12 +2,20 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; +import com.mojang.serialization.Lifecycle; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; -import net.minecraftforge.event.CreativeModeTabEvent; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistry; +import net.minecraftforge.registries.RegisterEvent; import org.junit.Test; import zone.moddev.mc.basepower.init.ItemGroups; import static org.junit.Assert.*; @@ -17,17 +25,21 @@ public class CreativeTabInitializationTest { net.minecraft.SharedConstants.tryDetectVersion(); net.minecraft.server.Bootstrap.bootStrap(); assertSame(Items.STICK, ItemGroups.show(Items.STICK)); - List registered = new ArrayList<>(); - ItemGroups.register(new CreativeModeTabEvent.Register((setup, key, before, after) -> { - registered.add(key); - var builder = new CreativeModeTab.Builder(CreativeModeTab.Row.TOP, 0); - setup.accept(builder); - return builder.build(); - })); + var registry = new MappedRegistry<>(Registries.CREATIVE_MODE_TAB, Lifecycle.stable()); + var event = RegisterEvent.class.getDeclaredConstructor(ResourceKey.class, ForgeRegistry.class, Registry.class); + event.setAccessible(true); + // Plain JUnit runs without the ModLauncher event bus transformer. + var tabs = ItemGroups.class.getDeclaredField("TABS"); + tabs.setAccessible(true); + var addEntries = DeferredRegister.class.getDeclaredMethod("addEntries", RegisterEvent.class); + addEntries.setAccessible(true); + addEntries.invoke(tabs.get(null), event.newInstance(Registries.CREATIVE_MODE_TAB, null, registry)); ItemGroups.show(Items.IRON_INGOT); ItemGroups.show(Items.STICK); - assertEquals(List.of(new ResourceLocation("basepower:machines")), registered); + var id = new ResourceLocation("basepower:machines"); + assertEquals(Set.of(id), registry.keySet()); var tab = ItemGroups.tab_powerAdvantage; + assertSame(tab, registry.get(id)); assertEquals("itemGroup.basepower", ((TranslatableContents) tab.getDisplayName().getContents()).getKey()); var field = CreativeModeTab.class.getDeclaredField("displayItemsGenerator"); field.setAccessible(true); diff --git a/src/test/java/zone/moddev/mc/basepower/resources/NativeBlockEntityFactoryTest.java b/src/test/java/zone/moddev/mc/basepower/resources/NativeBlockEntityFactoryTest.java index 866937f1..fe96ed00 100644 --- a/src/test/java/zone/moddev/mc/basepower/resources/NativeBlockEntityFactoryTest.java +++ b/src/test/java/zone/moddev/mc/basepower/resources/NativeBlockEntityFactoryTest.java @@ -5,7 +5,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Material; import org.junit.BeforeClass; import org.junit.Test; import org.objectweb.asm.ClassReader; @@ -26,7 +25,7 @@ public class NativeBlockEntityFactoryTest { } @Test public void nativeFactoriesKeepTheActualPositionAndFacing() { - BlockConveyor block = new BlockConveyor(Material.PISTON, 0.75F); + BlockConveyor block = new BlockConveyor(0.75F); BlockEntityType old = Entities.CONVEYOR; try { Entities.CONVEYOR = BlockEntityType.Builder.of(TileEntityConveyor::new, block).build(null); diff --git a/src/test/java/zone/moddev/mc/basepower/resources/NativeMachinePropertyTest.java b/src/test/java/zone/moddev/mc/basepower/resources/NativeMachinePropertyTest.java index dedc7981..efb2cfaf 100644 --- a/src/test/java/zone/moddev/mc/basepower/resources/NativeMachinePropertyTest.java +++ b/src/test/java/zone/moddev/mc/basepower/resources/NativeMachinePropertyTest.java @@ -4,7 +4,8 @@ import cyano.poweradvantage.api.ConduitType; import cyano.poweradvantage.api.simple.BlockSimplePowerConduit; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MapColor; +import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.server.Bootstrap; import net.minecraft.world.level.BlockGetter; @@ -23,30 +24,29 @@ public class NativeMachinePropertyTest { net.minecraftforge.registries.GameData.unfreezeData(); } - @Test public void materialConstructorsKeepTheLegacyNonSolidDefault() { - assertFalse(new MaterialMachine().defaultBlockState().canOcclude()); + @Test public void machineDefaultsKeepPistonResistanceAndNonOccludingRendering() { + var state = new PropertyMachine(GUIBlock.machineProperties(0.75F)).defaultBlockState(); + state.initCache(); + assertFalse(state.canOcclude()); + assertTrue(state.blocksMotion()); + assertEquals(PushReaction.BLOCK, state.getPistonPushReaction()); } @Test public void explicitNativePropertiesRetainBothSolidAndNonSolidChoices() { - assertTrue(new PropertyMachine(Block.Properties.of(Material.STONE)).defaultBlockState().canOcclude()); - assertFalse(new PropertyMachine(Block.Properties.of(Material.STONE).noOcclusion()) + assertTrue(new PropertyMachine(Block.Properties.of().mapColor(MapColor.STONE)).defaultBlockState().canOcclude()); + assertFalse(new PropertyMachine(Block.Properties.of().mapColor(MapColor.STONE).noOcclusion()) .defaultBlockState().canOcclude()); } @Test public void conveyorsRemainNonSolidWhenUsingExplicitNativeProperties() { - assertFalse(new BlockConveyor(Material.PISTON, 0.75F).defaultBlockState().canOcclude()); - assertFalse(new BlockConveyorFilter(Material.PISTON, 0.75F, TileEntityConveyor.class) + assertFalse(new BlockConveyor(0.75F).defaultBlockState().canOcclude()); + assertFalse(new BlockConveyorFilter(0.75F, TileEntityConveyor.class) .defaultBlockState().canOcclude()); } - private static final class MaterialMachine extends GUIBlock { - MaterialMachine() { super(Material.PISTON, 0.75F); } - @Override public BlockEntity newBlockEntity(net.minecraft.core.BlockPos pos, net.minecraft.world.level.block.state.BlockState state) { return null; } - } - @Test public void conduitSubclassesCanChooseNativePropertiesWithoutReplacingNetworkBehavior() { - PropertyConduit solid = new PropertyConduit(Block.Properties.of(Material.PISTON)); - PropertyConduit nonSolid = new PropertyConduit(Block.Properties.of(Material.PISTON).noOcclusion()); + PropertyConduit solid = new PropertyConduit(Block.Properties.of().mapColor(MapColor.STONE)); + PropertyConduit nonSolid = new PropertyConduit(Block.Properties.of().mapColor(MapColor.STONE).noOcclusion()); assertTrue(solid.defaultBlockState().canOcclude()); assertFalse(nonSolid.defaultBlockState().canOcclude()); assertEquals(6, nonSolid.defaultBlockState().getProperties().size()); diff --git a/src/test/java/zone/moddev/mc/basepower/resources/NativePlatformContractTest.java b/src/test/java/zone/moddev/mc/basepower/resources/NativePlatformContractTest.java index 48aaa1ce..ac11c8b8 100644 --- a/src/test/java/zone/moddev/mc/basepower/resources/NativePlatformContractTest.java +++ b/src/test/java/zone/moddev/mc/basepower/resources/NativePlatformContractTest.java @@ -54,17 +54,19 @@ public class NativePlatformContractTest { } @Test public void nativeLootLoaderCallsForgeJsonHookAndNotTheRemovedAdvantageBridge() throws Exception { - ClassNode node = read("net/minecraft/world/level/storage/loot/LootTables"); + ClassNode node = read("net/minecraft/world/level/storage/loot/LootDataType"); int calls = 0; for (MethodNode method : node.methods) for (AbstractInsnNode instruction : method.instructions.toArray()) { - if (!(instruction instanceof MethodInsnNode)) continue; - MethodInsnNode call = (MethodInsnNode) instruction; - assertNotEquals("zone/moddev/mc/basepower/recipe/PartsLoot", call.owner); - if (call.owner.equals("net/minecraftforge/common/ForgeHooks") && call.name.equals("loadLootTable")) { - assertEquals("(Lcom/google/gson/Gson;Lnet/minecraft/resources/ResourceLocation;" - + "Lcom/google/gson/JsonElement;ZLnet/minecraft/world/level/storage/loot/LootTables;)" - + "Lnet/minecraft/world/level/storage/loot/LootTable;", call.desc); - calls++; + if (instruction instanceof MethodInsnNode call) { + assertNotEquals("zone/moddev/mc/basepower/recipe/PartsLoot", call.owner); + } + if (instruction instanceof org.objectweb.asm.tree.InvokeDynamicInsnNode dynamic) { + for (Object argument : dynamic.bsmArgs) { + if (!(argument instanceof org.objectweb.asm.Handle target)) continue; + assertNotEquals("zone/moddev/mc/basepower/recipe/PartsLoot", target.getOwner()); + if (target.getOwner().equals("net/minecraftforge/common/ForgeHooks") + && target.getName().equals("getLootTableDeserializer")) calls++; + } } } assertEquals(1, calls); diff --git a/src/test/java/zone/moddev/mc/basepower/util/MachineCapabilitiesLifecycleTest.java b/src/test/java/zone/moddev/mc/basepower/util/MachineCapabilitiesLifecycleTest.java index 48145f3d..abb38278 100644 --- a/src/test/java/zone/moddev/mc/basepower/util/MachineCapabilitiesLifecycleTest.java +++ b/src/test/java/zone/moddev/mc/basepower/util/MachineCapabilitiesLifecycleTest.java @@ -8,11 +8,9 @@ import net.minecraft.core.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.IEnergyStorage; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -23,43 +21,43 @@ public class MachineCapabilitiesLifecycleTest { @BeforeClass public static void nativeCapabilityTokens() throws Exception { net.minecraft.SharedConstants.tryDetectVersion(); net.minecraft.server.Bootstrap.bootStrap(); - assertNotNull(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); - assertNotNull(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - assertNotNull(CapabilityEnergy.ENERGY); + assertNotNull(ForgeCapabilities.FLUID_HANDLER); + assertNotNull(ForgeCapabilities.ITEM_HANDLER); + assertNotNull(ForgeCapabilities.ENERGY); } @Test public void chunkUnloadCannotRecreateAdaptersOnAnUnremovedTile() { TestTank tank = new TestTank(); - LazyOptional fluid = tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, Direction.UP); - LazyOptional item = tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.DOWN); + LazyOptional fluid = tank.getCapability(ForgeCapabilities.FLUID_HANDLER, Direction.UP); + LazyOptional item = tank.getCapability(ForgeCapabilities.ITEM_HANDLER, Direction.DOWN); assertTrue(fluid.isPresent()); assertTrue(item.isPresent()); tank.onChunkUnloaded(); assertFalse(tank.isRemoved()); assertFalse(fluid.isPresent()); assertFalse(item.isPresent()); - assertFalse(tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, Direction.UP).isPresent()); - assertFalse(tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.DOWN).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.FLUID_HANDLER, Direction.UP).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.ITEM_HANDLER, Direction.DOWN).isPresent()); } @Test public void explicitInvalidationBlocksEverySidedAndUnsidedRequest() { TestTank tank = new TestTank(); tank.invalidateNow(); for (Direction face : Direction.values()) { - assertFalse(tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, face).isPresent()); - assertFalse(tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, face).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.FLUID_HANDLER, face).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.ITEM_HANDLER, face).isPresent()); } - assertFalse(tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null).isPresent()); - assertFalse(tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.FLUID_HANDLER, null).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.ITEM_HANDLER, null).isPresent()); } @Test public void clearRemovedCreatesFreshOptionalsWithoutRevivingOldOnes() { TestTank tank = new TestTank(); tank.getTank().setFluid(new cyano.poweradvantage.api.fluid.FluidStack(net.minecraft.world.level.material.Fluids.WATER, 500)); - LazyOptional old = tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + LazyOptional old = tank.getCapability(ForgeCapabilities.FLUID_HANDLER, null); tank.onChunkUnloaded(); tank.clearRemoved(); - LazyOptional current = tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + LazyOptional current = tank.getCapability(ForgeCapabilities.FLUID_HANDLER, null); assertTrue(current.isPresent()); assertNotSame(old, current); assertFalse(old.isPresent()); @@ -68,12 +66,12 @@ public class MachineCapabilitiesLifecycleTest { @Test public void invalidationListenersCannotReacquireAnotherAdapter() { TestTank tank = new TestTank(); - LazyOptional fluid = tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); - tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); + LazyOptional fluid = tank.getCapability(ForgeCapabilities.FLUID_HANDLER, null); + tank.getCapability(ForgeCapabilities.ITEM_HANDLER, null); AtomicBoolean called = new AtomicBoolean(), reacquired = new AtomicBoolean(); fluid.addListener(ignored -> { called.set(true); - reacquired.set(tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).isPresent()); + reacquired.set(tank.getCapability(ForgeCapabilities.ITEM_HANDLER, null).isPresent()); }); tank.onChunkUnloaded(); assertTrue(called.get()); @@ -84,23 +82,23 @@ public class MachineCapabilitiesLifecycleTest { TestTank tank = new TestTank(); tank.setRemoved(); tank.reviveNow(); - assertFalse(tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null).isPresent()); - assertFalse(tank.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.FLUID_HANDLER, null).isPresent()); + assertFalse(tank.getCapability(ForgeCapabilities.ITEM_HANDLER, null).isPresent()); tank.clearRemoved(); - assertTrue(tank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null).isPresent()); + assertTrue(tank.getCapability(ForgeCapabilities.FLUID_HANDLER, null).isPresent()); } @Test public void conveyorsFollowTheSameUnloadAndRevivalContract() { zone.moddev.mc.basepower.machines.conveyors.TileEntityConveyor conveyor = new zone.moddev.mc.basepower.machines.conveyors.TileEntityConveyor(net.minecraft.core.BlockPos.ZERO, net.minecraft.world.level.block.Blocks.HOPPER.defaultBlockState()); - LazyOptional old = conveyor.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); + LazyOptional old = conveyor.getCapability(ForgeCapabilities.ITEM_HANDLER, null); assertTrue(old.isPresent()); conveyor.onChunkUnloaded(); assertFalse(conveyor.isRemoved()); assertFalse(old.isPresent()); - assertFalse(conveyor.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).isPresent()); + assertFalse(conveyor.getCapability(ForgeCapabilities.ITEM_HANDLER, null).isPresent()); conveyor.clearRemoved(); - LazyOptional current = conveyor.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); + LazyOptional current = conveyor.getCapability(ForgeCapabilities.ITEM_HANDLER, null); assertTrue(current.isPresent()); assertNotSame(old, current); } @@ -108,13 +106,13 @@ public class MachineCapabilitiesLifecycleTest { @Test public void explicitNativeRevivalRestoresConverterEnergyWithoutLosingItsBuffer() { TestConverter converter = new TestConverter(); converter.receiveEnergy(200, false); - LazyOptional old = converter.getCapability(CapabilityEnergy.ENERGY, null); + LazyOptional old = converter.getCapability(ForgeCapabilities.ENERGY, null); assertTrue(old.isPresent()); converter.onChunkUnloaded(); assertFalse(old.isPresent()); - assertFalse(converter.getCapability(CapabilityEnergy.ENERGY, null).isPresent()); + assertFalse(converter.getCapability(ForgeCapabilities.ENERGY, null).isPresent()); converter.reviveNow(); - LazyOptional current = converter.getCapability(CapabilityEnergy.ENERGY, null); + LazyOptional current = converter.getCapability(ForgeCapabilities.ENERGY, null); assertTrue(current.isPresent()); assertNotSame(old, current); assertEquals(200, converter.getEnergyStored()); @@ -122,11 +120,11 @@ public class MachineCapabilitiesLifecycleTest { @Test public void converterEnergyIsUnavailableDuringOtherAdapterNotifications() { TestConverter converter = new TestConverter(); - LazyOptional item = converter.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); + LazyOptional item = converter.getCapability(ForgeCapabilities.ITEM_HANDLER, null); AtomicBoolean called = new AtomicBoolean(), reacquired = new AtomicBoolean(); item.addListener(ignored -> { called.set(true); - reacquired.set(converter.getCapability(CapabilityEnergy.ENERGY, null).isPresent()); + reacquired.set(converter.getCapability(ForgeCapabilities.ENERGY, null).isPresent()); }); converter.onChunkUnloaded(); assertTrue(called.get()); diff --git a/test-rig/NATIVE1201.md b/test-rig/NATIVE1201.md new file mode 100644 index 00000000..69224155 --- /dev/null +++ b/test-rig/NATIVE1201.md @@ -0,0 +1,49 @@ +# Advantage Works on Minecraft 1.20.1 + +Use Java 17, Forge 47.4.10 and the exact jars listed in +[`profiles/native1201/`](profiles/native1201/). When testing upgrades with +Base Metals installed, use the pinned build with the shared migration hook. +An older Base Metals jar can convert the chunk before basePower can read it. + +From the basePower checkout, build all three mods, then run: + +```powershell +.\gradlew.bat -p test-rig check build runnerJar verifyHarnessIsolation verifyWorksNative1201Inputs +.\gradlew.bat prepareCombinedEclipseLaunch +``` + +Refresh the Gradle project in Eclipse. Use `runClientAllAdvantage.launch` +for all three mods, or `runClient.launch` for basePower alone. Neither command +opens a world. Make a separate copy before testing a world upgrade. + +To walk around a disposable Works server, run +`gradlew.bat -p test-rig runWorksPackagedCurrent` and join localhost. +Use `stop` in the server console to save and exit. Earlier worlds and +results are left alone. + +## Automated checks + +The packaged and decoupled profiles cover the same 21 stations. The +world-generation profiles check fallback ores, Mineralogy coexistence and +the import of existing OreSpawn settings. + +The Python runners in `migration/` take an installed Forge server seed, a +sealed inventory of its files, the inventory SHA-256 and a hash-pinned jar +profile. Use `native1201.py --help` for the inventory command. Keep source +saves and receipts outside the output directories. + +- `native1201_legacy_world.py` and `native1201_modern_upgrade.py` compare saved + and live state before operation and after a full process restart. +- `native1201_broad.py` commissions every station. `native1201_networks.py` + checks partial unload, pipe reconnects, extended drills and capabilities. +- `native1201_actors.py` and `native1201_respawn.py` check saved players, + entities, dimensions and server-side death and respawn. +- `native1201_recipes.py` checks ingredients, unlocks and survival progression + in all three modes. Its exports also feed the + [graphical client check](client-resources/README.md). +- `native1201_endurance.py` defaults to 30 measured minutes. Pass + `--retained ` to exercise a migrated world alongside the + fresh one. `audit_native1201_endurance.py` independently checks the ledgers. + +Server results do not certify textures, machine screen layouts or real client +login. Keep those results separate from the graphical and manual checks. diff --git a/test-rig/build.gradle b/test-rig/build.gradle index 26d68d69..ad5fa8ab 100644 --- a/test-rig/build.gradle +++ b/test-rig/build.gradle @@ -6,8 +6,8 @@ plugins { id 'net.minecraftforge.gradle' version '7.0.34' } -ext.forge45MavenizerDefault = '../../../../MinecraftMineralogy/OS119/OreSpawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar' -apply from: '../gradle/forge45-mavenizer.gradle' +ext.forge47MavenizerDefault = '../../../../MinecraftMineralogy/OS1201/OreSpawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar' +apply from: '../gradle/forge47-mavenizer.gradle' // Saves, pinned inputs and evidence are siblings, never Gradle cleanup targets. layout.buildDirectory = layout.projectDirectory.dir('build/gradle') @@ -70,7 +70,7 @@ repositories { } def powerCompileJar = file(project.findProperty('powerAdvantageDeobfJar') - ?: '../build/libs-dev/basePower-2.4.11.119041-deobf.jar') + ?: '../build/libs-dev/basePower-2.4.12.120011-deobf.jar') dependencies { implementation minecraft.dependency( @@ -105,15 +105,15 @@ tasks.register('verifyWorksCompileInputPin') { inputs.property('sha256', project.poweradvantage_deobf_sha256) inputs.property('sourceCommit', project.poweradvantage_source_commit) doLast { - if (!powerCompileJar.isFile()) throw new GradleException("Missing 1.19.4 Power compile input: ${powerCompileJar}") + if (!powerCompileJar.isFile()) throw new GradleException("Missing 1.20.1 Power compile input: ${powerCompileJar}") String actual = java.security.MessageDigest.getInstance('SHA-256') .digest(powerCompileJar.bytes).encodeHex().toString().toUpperCase(Locale.ROOT) if (actual != project.poweradvantage_deobf_sha256) { throw new GradleException("Power compile input changed: ${actual}; obtain a new parent pin") } - if (project.poweradvantage_source_commit != 'c9995315e2aee9d9bffec8eb8b1191ad8a0faeb7' + if (project.poweradvantage_source_commit != '83a3f028ffad220fe2f3cc4983a9340dde2295a8' || project.poweradvantage_pin_status != 'SOURCE_AND_ARTIFACT_PINNED') { - throw new GradleException('The harness requires the verified 1.19.4 Power source pin') + throw new GradleException('The harness requires the verified 1.20.1 Power source pin') } } } @@ -185,7 +185,7 @@ def registerWorksRunner = { String taskName, String profileName, boolean automat classpath = sourceSets.runner.runtimeClasspath mainClass = 'zone.moddev.mc.advantageworks.runner.WorksRunner' if (!automated) standardInput = System.in - args '--profile', file("profiles/native119/${profileName}.json").absolutePath + args '--profile', file("profiles/native1201/${profileName}.json").absolutePath if (automated) args '--automated' if (project.hasProperty('worksStations')) { args '--stations', project.property('worksStations').toString() @@ -200,7 +200,7 @@ def registerWorksRunner = { String taskName, String profileName, boolean automat } registerWorksRunner('runWorksDev', 'dev-core', false, - 'Builds and launches a disposable interactive 1.19.4 Advantage Works development server.') + 'Builds and launches a disposable interactive 1.20.1 Advantage Works development server.') registerWorksRunner('verifyWorksDev', 'dev-core', true, 'Generates, checks, restarts, and rechecks the disposable development works.') registerWorksRunner('verifyWorksTechProgression', 'dev-core-tech-progression', true, @@ -224,13 +224,13 @@ registerWorksRunner('verifyWorksWorldgenLegacyImport', 'worldgen-legacy-import', registerWorksRunner('runWorksPackagedCurrent', 'packaged-current', false, 'Launches the complete packaged works on localhost for manual inspection.') -tasks.register('verifyWorksNative119Inputs', JavaExec) { +tasks.register('verifyWorksNative1201Inputs', JavaExec) { group = 'verification' - description = 'Checks 1.19.4 candidate identities and hashes without creating or opening a world.' + description = 'Checks 1.20.1 candidate identities and hashes without creating or opening a world.' dependsOn tasks.named('runnerClasses'), tasks.named('jar'), releaseJar classpath = sourceSets.runner.runtimeClasspath mainClass = 'zone.moddev.mc.advantageworks.runner.WorksRunner' - args '--profile', file("profiles/native119/${project.findProperty('worksProfile') ?: 'packaged-current'}.json").absolutePath, + args '--profile', file("profiles/native1201/${project.findProperty('worksProfile') ?: 'packaged-current'}.json").absolutePath, '--validate-only' } @@ -239,7 +239,7 @@ tasks.register('verifyHarnessIsolation') { description = 'Confirms the PowerAdvantage release contains no test-harness content.' doLast { File powerJar = file(project.findProperty('powerAdvantageReleaseJar') - ?: '../build/libs/basePower-2.4.11.119041.jar') + ?: '../build/libs/basePower-2.4.12.120011.jar') if (!powerJar.isFile()) { throw new GradleException("Build PowerAdvantage first: ${powerJar}") } diff --git a/test-rig/client-resources/README.md b/test-rig/client-resources/README.md index df38e2ad..baa3dac2 100644 --- a/test-rig/client-resources/README.md +++ b/test-rig/client-resources/README.md @@ -1,26 +1,26 @@ # Native Client Resource Check -This disposable Minecraft 1.19.4 / Forge 45.4.0 client checks models, textures, +This disposable Minecraft 1.20.1 / Forge 47.4.10 client checks models, textures, translations, recipe-book cells and machine screens after Minecraft loads them. It registers no gameplay content, opens no world and closes when finished. The probe is excluded from release jars and ordinary Eclipse launches. -See [port status](../../docs/1.19/PORT-STATUS.md) for current qualification. +See [port status](../../docs/1.20.1/PORT-STATUS.md) for current qualification. Earlier-version results do not qualify this version. Use Java 17 for Gradle, compilation and the client and server runners. The -target is official 1.19.4 mappings with MCP `20230314.122934`. +target is official 1.20.1 mappings with MCP `20230612.114412`. ## Build And Run ```powershell ./gradlew.bat check clientResourceProbeJar verifyEclipseProductionClasspath prepareCombinedEclipseLaunch ./test-rig/client-resources/test-launcher.ps1 -./test-rig/client-resources/run.ps1 -JavaHome '' -LaunchProfile runClientAllAdvantage.launch -RequireExtensions -MachineGuiLayouts -ChildRendererGeometry -RecipeBookFixtures '/unlock' -PreflightOnly -./test-rig/client-resources/run.ps1 -JavaHome '' -LaunchProfile runClientAllAdvantage.launch -RequireExtensions -MachineGuiLayouts -ChildRendererGeometry -RecipeBookFixtures '/unlock' +./test-rig/client-resources/run.ps1 -JavaHome '' -LaunchProfile runClientAllAdvantage.launch -RequireExtensions -MachineGuiLayouts -ChildRendererGeometry -RecipeBookFixtures '/unlock' -PreflightOnly +./test-rig/client-resources/run.ps1 -JavaHome '' -LaunchProfile runClientAllAdvantage.launch -RequireExtensions -MachineGuiLayouts -ChildRendererGeometry -RecipeBookFixtures '/unlock' ``` -The combined launch requires Power `2.4.11.119041`, Steam `2.2.12.119041` and -Electric `2.2.12.119041`. Pin the exact rebuilt jars in `profiles/native119` +The combined launch requires Power `2.4.12.120011`, Steam `2.2.13.120011` and +Electric `2.2.13.120011`. Pin the exact rebuilt jars in `profiles/native1201` before regenerating it. Omitting the combined profile retains Power-only scope. Normal Eclipse launches contain production code only. @@ -39,10 +39,10 @@ is provenance, not proof that the selected loose output equals that jar. ## Recipe Fixtures -Generate fresh exports from the packaged 1.19.4 candidates, not a historical run: +Generate fresh exports from the packaged 1.20.1 candidates, not a historical run: ```powershell - -B test-rig/migration/native119_recipes.py --profile test-rig/profiles/native119/packaged-current.json --seed '' --inventory '' --inventory-sha256 '' --java17 '/bin/java.exe' --port 25577 --output test-rig/build/native119-recipes-new + -B test-rig/migration/native1201_recipes.py --profile test-rig/profiles/native1201/packaged-current.json --seed '' --inventory '' --inventory-sha256 '' --java17 '/bin/java.exe' --port 25577 --output test-rig/build/native1201-recipes-new ``` Use an existing Python 3.11+ environment with `migration/requirements.txt`. diff --git a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/ClientResourceProbe.java b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/ClientResourceProbe.java index ee0d7c91..5eb0738b 100644 --- a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/ClientResourceProbe.java +++ b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/ClientResourceProbe.java @@ -47,8 +47,8 @@ public final class ClientResourceProbe { try { result.addProperty("minecraft", net.minecraftforge.versions.mcp.MCPVersion.getMCVersion()); result.addProperty("forge", net.minecraftforge.versions.forge.ForgeVersion.getVersion()); - require("1.19.4".equals(result.get("minecraft").getAsString()) - && "45.4.0".equals(result.get("forge").getAsString()), "Wrong native client target"); + require("1.20.1".equals(result.get("minecraft").getAsString()) + && "47.4.10".equals(result.get("forge").getAsString()), "Wrong native client target"); require(minecraft.level == null && minecraft.player == null && !minecraft.hasSingleplayerServer(), "Resource probe must not open a world or connect to a server"); verifyNetworkBootstrap(result); @@ -67,9 +67,9 @@ public final class ClientResourceProbe { result.add("mod_versions", versions); require(versions.has("basepower") && zone.moddev.mc.basepower.PowerAdvantage.VERSION .equals(versions.get("basepower").getAsString()), "Power metadata does not match the compiled version"); - require("2.4.11.119041".equals(versions.get("basepower").getAsString()), "Wrong native Power candidate"); + require("2.4.12.120011".equals(versions.get("basepower").getAsString()), "Wrong native Power candidate"); for (String id : new String[]{"basesteam", "baseelectric"}) { - if (versions.has(id)) require("2.2.12.119041".equals(versions.get(id).getAsString()), "Wrong native expansion candidate: " + id); + if (versions.has(id)) require("2.2.13.120011".equals(versions.get(id).getAsString()), "Wrong native expansion candidate: " + id); } require(minecraft.getModelManager().getMissingModel() != null, "Timed out before model baking"); require(minecraft.getOverlay() == null, "Timed out before native resource loading completed"); diff --git a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/MachineGuiLayoutProbe.java b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/MachineGuiLayoutProbe.java index 921ad827..90553d94 100644 --- a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/MachineGuiLayoutProbe.java +++ b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/MachineGuiLayoutProbe.java @@ -3,7 +3,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; import cyano.poweradvantage.api.GUIBlock; import cyano.poweradvantage.api.PoweredEntity; @@ -25,6 +24,9 @@ import javax.imageio.ImageIO; import net.minecraft.world.level.block.Block; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.Font; +import net.minecraft.world.inventory.tooltip.TooltipComponent; import net.minecraft.client.player.LocalPlayer; import com.mojang.blaze3d.pipeline.RenderTarget; import net.minecraft.client.multiplayer.ClientLevel; @@ -36,6 +38,7 @@ import net.minecraft.core.BlockPos; import net.minecraftforge.registries.ForgeRegistries; import zone.moddev.mc.basepower.registry.MachineGUIRegistry; +import org.joml.Vector3f; /** Renders every registered machine screen, not just its detached decorations. */ final class MachineGuiLayoutProbe { @@ -106,7 +109,9 @@ static void verify(Minecraft minecraft, JsonObject result) { Field clientSide = net.minecraft.world.level.Level.class.getDeclaredField("isClientSide"); clientSide.setAccessible(true); clientSide.setBoolean(world, true); - player.level = world; + Field playerLevel = net.minecraft.world.entity.Entity.class.getDeclaredField("level"); + playerLevel.setAccessible(true); + playerLevel.set(player, world); tile.setLevel(world); SimpleMachineGUI.Container menu = ((SimpleMachineGUI) definition).createMenu(1, inventory, (Container) tile); require(expectations.getAsJsonObject("machines").has(id), "No human-facing label expectation for " + id); @@ -168,7 +173,7 @@ static void verify(Minecraft minecraft, JsonObject result) { verifyLongName(minecraft, (SimpleMachineGUI) definition, menu, inventory); } if (block == zone.moddev.mc.basepower.init.Blocks.metal_storage_tank) { - verifyHelperLimits(screen); + verifyHelperLimits(minecraft, screen); } row.addProperty("renders", renders); row.addProperty("tooltip_and_inventory_hitbox", "PASS"); @@ -253,16 +258,18 @@ private static BufferedImage render(Minecraft minecraft, RecordingScreen screen, try { RenderSystem.clearColor(0.12F, 0.18F, 0.23F, 1); RenderSystem.clear(16384 | 256, Minecraft.ON_OSX); + GuiGraphics graphics = screen.recordingGraphics(minecraft); if (backgroundOnly) { LabelMode original = screen.labels; screen.labels = LabelMode.HIDDEN; - screen.render(new PoseStack(), -100, -100, 0F); + screen.render(graphics, -100, -100, 0F); screen.labels = original; } else { Slot hotbar = screen.getMenu().slots.get(screen.getMenu().slots.size() - 9); - screen.render(new PoseStack(), screen.hoverTitle ? screen.width / 2 : hover ? screen.getLeft() + hotbar.x + 1 : -100, + screen.render(graphics, screen.hoverTitle ? screen.width / 2 : hover ? screen.getLeft() + hotbar.x + 1 : -100, screen.hoverTitle ? screen.getTop() + 4 : hover ? screen.getTop() + hotbar.y + 1 : -100, 0F); } + graphics.flush(); ByteBuffer pixels = ByteBuffer.allocateDirect(width * height * 4); RenderSystem.readPixels(0, 0, width, height, 6408, 5121, pixels); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); @@ -354,7 +361,7 @@ private static void require(boolean value, String message) { if (!value) throw new IllegalStateException(message); } - private static void verifyHelperLimits(RecordingScreen screen) throws Exception { + private static void verifyHelperLimits(Minecraft minecraft, RecordingScreen screen) throws Exception { for (String name : new String[]{"zone.moddev.mc.baseelectric.gui.GUIHelper", "zone.moddev.mc.basesteam.gui.GUIHelper"}) { if (!net.minecraftforge.fml.ModList.get().isLoaded(name.contains("baseelectric") ? "baseelectric" : "basesteam")) continue; @@ -363,9 +370,19 @@ private static void verifyHelperLimits(RecordingScreen screen) throws Exception for (String method : methods) { Method draw = Class.forName(name).getMethod(method, int.class, int.class, float.class, SimpleMachineGUI.GUIContainer.class); for (float value : new float[]{-1F, 0F, 0.5F, 1F, 15F, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY}) { - screen.draws.clear(); - draw.invoke(null, screen.getLeft() + 44, screen.getTop() + 46, value, screen); - screen.verifyDrawBounds(); + screen.helperCheck = () -> { + try { + screen.draws.clear(); + draw.invoke(null, screen.getLeft() + 44, screen.getTop() + 46, value, screen); + screen.verifyDrawBounds(); + require((Float.isFinite(value) && value > 0) == !screen.draws.isEmpty(), + "Wrong draw count for " + method + " at " + value); + } catch (ReflectiveOperationException failure) { + throw new IllegalStateException("Cannot render " + method, failure); + } + }; + render(minecraft, screen, VIEWPORTS[0], false); + require(screen.helperCheck == null, "Progress helper did not run inside renderBg"); } } } @@ -385,7 +402,10 @@ private GuiWorld() { } private static final class RecordingScreen extends SimpleMachineGUI.GUIContainer { - private final List draws = new ArrayList<>(); + private record DrawBounds(float left, float top, float right, float bottom, int u, int v, int width, int height) {} + + private final List draws = new ArrayList<>(); + private Runnable helperCheck; private int tooltipCalls; private int itemTooltipCalls; private LabelMode labels = LabelMode.PRODUCTION; @@ -398,8 +418,8 @@ private static final class RecordingScreen extends SimpleMachineGUI.GUIContainer this.expectedTitle = expectedTitle; this.expectedInventory = expectedInventory; } - @Override protected void renderLabels(PoseStack matrices, int x, int y) { - if (labels == LabelMode.PRODUCTION) { super.renderLabels(matrices, x, y); return; } + @Override protected void renderLabels(GuiGraphics graphics, int x, int y) { + if (labels == LabelMode.PRODUCTION) { super.renderLabels(graphics, x, y); return; } if (labels == LabelMode.HIDDEN) return; if (labels != LabelMode.INVENTORY_ONLY) { String text = labels == LabelMode.WRONG_TEXT ? "Untranslated machine.name" : expectedTitle; @@ -408,39 +428,63 @@ private static final class RecordingScreen extends SimpleMachineGUI.GUIContainer text += "..."; } int textX = (176 - font.width(text)) / 2; - font.drawShadow(matrices, text, textX, labels == LabelMode.OVER_GAUGE ? 20 : 1, 0xFFFFFF); + graphics.drawString(font, text, textX, labels == LabelMode.OVER_GAUGE ? 20 : 1, 0xFFFFFF); } - if (labels != LabelMode.TITLE_ONLY) font.drawShadow(matrices, expectedInventory, 8, 140, 0xFFFFFF); + if (labels != LabelMode.TITLE_ONLY) graphics.drawString(font, expectedInventory, 8, 140, 0xFFFFFF); } - @Override public void render(PoseStack matrices, int x, int y, float ticks) { + @Override public void render(GuiGraphics graphics, int x, int y, float ticks) { draws.clear(); tooltipCalls = 0; itemTooltipCalls = 0; titleTooltip = null; - super.render(matrices, x, y, ticks); + super.render(graphics, x, y, ticks); } - @Override protected void renderTooltip(PoseStack matrices, int x, int y) { + @Override protected void renderTooltip(GuiGraphics graphics, int x, int y) { tooltipCalls++; - super.renderTooltip(matrices, x, y); + super.renderTooltip(graphics, x, y); } - @Override public void renderTooltip(PoseStack matrices, net.minecraft.world.item.ItemStack item, int x, int y) { - itemTooltipCalls++; - super.renderTooltip(matrices, item, x, y); - } - @Override public void renderTooltip(PoseStack matrices, net.minecraft.network.chat.Component text, int x, int y) { - titleTooltip = text.getString(); - super.renderTooltip(matrices, text, x, y); + GuiGraphics recordingGraphics(Minecraft minecraft) { + return new GuiGraphics(minecraft, minecraft.renderBuffers().bufferSource()) { + @Override public void renderTooltip(Font font, List lines, + java.util.Optional component, net.minecraft.world.item.ItemStack item, + int x, int y) { + itemTooltipCalls++; + super.renderTooltip(font, lines, component, item, x, y); + } + + @Override public void renderTooltip(Font font, net.minecraft.network.chat.Component text, int x, int y) { + titleTooltip = text.getString(); + super.renderTooltip(font, text, x, y); + } + }; } Slot hovered() { return hoveredSlot; } - @Override public void blit(int x, int y, int u, int v, int width, int height) { - draws.add(new int[]{x - getLeft(), y - getTop(), u, v, width, height}); - super.blit(x, y, u, v, width, height); + @Override public void blit(net.minecraft.resources.ResourceLocation texture, + int x, int y, int u, int v, int width, int height) { + var pose = getMatrices().last().pose(); + float left = Float.POSITIVE_INFINITY, top = Float.POSITIVE_INFINITY; + float right = Float.NEGATIVE_INFINITY, bottom = Float.NEGATIVE_INFINITY; + for (int px : new int[]{x, x + width}) for (int py : new int[]{y, y + height}) { + Vector3f corner = pose.transformPosition(px, py, 0, new Vector3f()); + float relativeX = corner.x - getLeft(), relativeY = corner.y - getTop(); + left = Math.min(left, relativeX); + top = Math.min(top, relativeY); + right = Math.max(right, relativeX); + bottom = Math.max(bottom, relativeY); + } + draws.add(new DrawBounds(left, top, right, bottom, u, v, width, height)); + super.blit(texture, x, y, u, v, width, height); + if (helperCheck != null) { + Runnable check = helperCheck; + helperCheck = null; + check.run(); + } } void verifyDrawBounds() { - for (int[] draw : draws) { - require(draw[4] >= 0 && draw[5] >= 0 && draw[0] >= 0 && draw[1] >= 0 - && draw[0] + draw[4] <= getXSize() && draw[1] + draw[5] <= getYSize() - && draw[2] >= 0 && draw[3] >= 0 && draw[2] + draw[4] <= 256 && draw[3] + draw[5] <= 256, - "Decoration outside screen or texture: " + java.util.Arrays.toString(draw)); - if (draw[5] > 0) require(draw[1] >= 12 && (draw[1] + draw[5] <= 140 || draw[1] >= 150), - "Artwork intrudes into a required label row: " + java.util.Arrays.toString(draw)); + for (DrawBounds draw : draws) { + require(draw.width >= 0 && draw.height >= 0 && draw.left >= 0 && draw.top >= 0 + && draw.right <= getXSize() && draw.bottom <= getYSize() + && draw.u >= 0 && draw.v >= 0 && draw.u + draw.width <= 256 && draw.v + draw.height <= 256, + "Decoration outside screen or texture: " + draw); + if (draw.height > 0) require(draw.top >= 12 && (draw.bottom <= 140 || draw.top >= 150), + "Artwork intrudes into a required label row: " + draw); } } } diff --git a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/NativeGuiProjection.java b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/NativeGuiProjection.java index 3e02b863..f5d7ef5d 100644 --- a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/NativeGuiProjection.java +++ b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/NativeGuiProjection.java @@ -2,15 +2,18 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexSorting; import org.joml.Matrix4f; /** Scoped native shader projection for framebuffer-based screen tests. */ final class NativeGuiProjection implements AutoCloseable { private final Matrix4f projection = new Matrix4f(RenderSystem.getProjectionMatrix()); + private final VertexSorting sorting = RenderSystem.getVertexSorting(); private final PoseStack modelView = RenderSystem.getModelViewStack(); NativeGuiProjection(float width, float height, float near, float far, float depth) { - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, width, height, 0, near, far)); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, width, height, 0, near, far), + VertexSorting.ORTHOGRAPHIC_Z); modelView.pushPose(); modelView.setIdentity(); modelView.translate(0, 0, depth); @@ -20,6 +23,6 @@ final class NativeGuiProjection implements AutoCloseable { @Override public void close() { modelView.popPose(); RenderSystem.applyModelViewMatrix(); - RenderSystem.setProjectionMatrix(projection); + RenderSystem.setProjectionMatrix(projection, sorting); } } diff --git a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/RecipeBookGroupingProbe.java b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/RecipeBookGroupingProbe.java index e9ff1ce9..ac44313a 100644 --- a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/RecipeBookGroupingProbe.java +++ b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/RecipeBookGroupingProbe.java @@ -54,15 +54,15 @@ static void verify(Minecraft minecraft, JsonObject report) { net.minecraft.nbt.CompoundTag saved; try (java.io.InputStream input = Files.newInputStream(root.resolve("server-registries.dat"))) { net.minecraft.nbt.CompoundTag level = net.minecraft.nbt.NbtIo.readCompressed(input); - require("1.19.4".equals(level.getCompound("Data").getCompound("Version").getString("Name")), - "Recipe fixture is not a native 1.19.4 server export"); + require("1.20.1".equals(level.getCompound("Data").getCompound("Version").getString("Name")), + "Recipe fixture is not a native 1.20.1 server export"); net.minecraft.nbt.ListTag mods = level.getCompound("fml").getList("LoadingModList", 10); boolean nativeForge = false; for (int i = 0; i < mods.size(); i++) { net.minecraft.nbt.CompoundTag mod = mods.getCompound(i); - if ("forge".equals(mod.getString("ModId"))) nativeForge = "45.4.0".equals(mod.getString("ModVersion")); + if ("forge".equals(mod.getString("ModId"))) nativeForge = "47.4.10".equals(mod.getString("ModVersion")); } - require(nativeForge, "Recipe fixture was not saved by Forge 45.4.0"); + require(nativeForge, "Recipe fixture was not saved by Forge 47.4.10"); saved = level.getCompound("fml").getCompound("Registries"); } String itemRegistry = net.minecraftforge.registries.ForgeRegistries.ITEMS.getRegistryName().toString(); @@ -149,6 +149,7 @@ private static void render(Minecraft minecraft, ClientRecipeBook book) throws Ex RenderSystem.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); net.minecraft.world.inventory.CraftingMenu menu = new net.minecraft.world.inventory.CraftingMenu(0, new net.minecraft.world.entity.player.Inventory(null)); require(menu.getRecipeBookType() == net.minecraft.world.inventory.RecipeBookType.CRAFTING, "Wrong native crafting menu type"); + var graphics = new net.minecraft.client.gui.GuiGraphics(minecraft, minecraft.renderBuffers().bufferSource()); for (int i = 0; i < shown.size(); i++) { int x = 10 + (i % 5) * 198, y = 12 + (i / 5) * 55; RecipeButton button = new RecipeButton(); @@ -163,9 +164,10 @@ private static void render(Minecraft minecraft, ClientRecipeBook book) throws Ex } } button.setPosition(x, y); - button.render(new com.mojang.blaze3d.vertex.PoseStack(), -1, -1, 1F); - minecraft.font.draw(new com.mojang.blaze3d.vertex.PoseStack(), shown.get(i).getRecipes().get(0).getResultItem(net.minecraft.core.RegistryAccess.EMPTY).getDisplayName().getString(), x + 30, y + 8, 0xFFFFFF); + button.render(graphics, -1, -1, 1F); + graphics.drawString(minecraft.font, shown.get(i).getRecipes().get(0).getResultItem(net.minecraft.core.RegistryAccess.EMPTY).getDisplayName(), x + 30, y + 8, 0xFFFFFF, false); } + graphics.flush(); ByteBuffer pixels = ByteBuffer.allocateDirect(width * height * 4); RenderSystem.readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); diff --git a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/TankVisualProbe.java b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/TankVisualProbe.java index c4678ea0..8da44007 100644 --- a/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/TankVisualProbe.java +++ b/test-rig/client-resources/java/zone/moddev/mc/advantageworks/client/TankVisualProbe.java @@ -17,7 +17,7 @@ import net.minecraft.world.level.BlockGetter; import zone.moddev.mc.basepower.gui.FilteredFluidTankGUI; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import zone.moddev.mc.basepower.registry.MachineGUIRegistry; @@ -44,7 +44,7 @@ static void verify(Minecraft minecraft, JsonObject result) { MetalTankTileEntity serverTank = new MetalTankTileEntity(BlockPos.ZERO, zone.moddev.mc.basepower.init.Blocks.metal_storage_tank.defaultBlockState()); - IFluidHandler handler = serverTank.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, Direction.UP) + IFluidHandler handler = serverTank.getCapability(ForgeCapabilities.FLUID_HANDLER, Direction.UP) .orElseThrow(() -> new IllegalStateException("Metal tank has no native Forge fluid capability")); require(handler.fill(new FluidStack(net.minecraft.world.level.material.Fluids.WATER, 10000), FluidAction.SIMULATE) == 10000 && serverTank.getTank().getFluidAmount() == 0, "Native simulated fill changed the tank"); @@ -83,18 +83,22 @@ private static boolean floorVisible(final BlockState tank) { private static int renderWater(Minecraft minecraft, MetalTankTileEntity tile) { FilteredFluidTankGUI definition = new FilteredFluidTankGUI(new ResourceLocation("basepower", "textures/gui/container/fluid_metal_tank_gui.png")); - final int width = 128, height = 96; + final int width = 176, height = 240; Inventory inventory = new Inventory(null); SimpleMachineGUI.Container container = definition.createMenu(1, inventory, tile); require(container.getType() == MachineGUIRegistry.TYPE && MachineGUIRegistry.TYPE != null, "Tank GUI is not backed by the registered native container type"); - SimpleMachineGUI.GUIContainer screen = container.createScreen(inventory, net.minecraft.network.chat.Component.literal("Tank probe")); + var screen = definition.new GUIContainer(container, inventory, net.minecraft.network.chat.Component.literal("Tank probe")) { + void renderTank(net.minecraft.client.gui.GuiGraphics graphics) { + renderBg(graphics, 0F, -100, -100); + } + }; screen.init(minecraft, width, height); require(screen.getMinecraft() == minecraft, "Native tank screen was not initialized"); tile.getTank().setFluid(new cyano.poweradvantage.api.fluid.FluidStack(net.minecraft.world.level.material.Fluids.WATER, 10000)); RenderTarget framebuffer = new com.mojang.blaze3d.pipeline.TextureTarget(width, height, true, Minecraft.ON_OSX); framebuffer.bindWrite(true); - NativeGuiProjection projection = new NativeGuiProjection(width, height, -1, 1, 0); + NativeGuiProjection projection = new NativeGuiProjection(width, height, 1000, 3000, -2000); RenderSystem.disableDepthTest(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); @@ -102,7 +106,9 @@ private static int renderWater(Minecraft minecraft, MetalTankTileEntity tile) { try { RenderSystem.clearColor(0F, 0F, 0F, 1F); RenderSystem.clear(GL_COLOR_BUFFER_BIT, Minecraft.ON_OSX); - definition.drawGUIDecorations(tile, screen, 0, 0, 0F); + var graphics = new net.minecraft.client.gui.GuiGraphics(minecraft, minecraft.renderBuffers().bufferSource()); + screen.renderTank(graphics); + graphics.flush(); ByteBuffer pixels = ByteBuffer.allocateDirect(width * height * 4); RenderSystem.readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); @@ -114,7 +120,7 @@ private static int renderWater(Minecraft minecraft, MetalTankTileEntity tile) { } } ImageIO.write(image, "png", new File("tank-water-gauge.png")); - return image.getRGB(88, 39) & 0xFFFFFF; + return image.getRGB(88, 51) & 0xFFFFFF; } catch (IOException failure) { throw new IllegalStateException("Could not retain the native tank gauge image", failure); } finally { diff --git a/test-rig/client-resources/resources/META-INF/mods.toml b/test-rig/client-resources/resources/META-INF/mods.toml index b1fc7ffc..8b829092 100644 --- a/test-rig/client-resources/resources/META-INF/mods.toml +++ b/test-rig/client-resources/resources/META-INF/mods.toml @@ -1,5 +1,5 @@ modLoader="javafml" -loaderVersion="[45,46)" +loaderVersion="[47,48)" license="GPL-3.0-only" [[mods]] @@ -11,20 +11,20 @@ description='''Build-only model, texture and translation checks. Never distribut [[dependencies.advantageclientresources]] modId="basepower" mandatory=true -versionRange="[2.4.11.119041]" +versionRange="[2.4.12.120011]" ordering="AFTER" side="CLIENT" [[dependencies.advantageclientresources]] modId="forge" mandatory=true -versionRange="[45.4.0]" +versionRange="[47.4.10]" ordering="NONE" side="CLIENT" [[dependencies.advantageclientresources]] modId="minecraft" mandatory=true -versionRange="[1.19.4]" +versionRange="[1.20.1]" ordering="NONE" side="CLIENT" diff --git a/test-rig/client-resources/run.ps1 b/test-rig/client-resources/run.ps1 index d866969b..2fde213e 100644 --- a/test-rig/client-resources/run.ps1 +++ b/test-rig/client-resources/run.ps1 @@ -30,22 +30,22 @@ function Assert-NativeMetadata([string]$Metadata, [string]$Id) { # Match the known single-mod header, not dependency modId/versionRange fields. $header = [regex]::Match($Metadata, '(?ms)^\[\[mods\]\]\s*(.*?)(?=^\[|\z)').Groups[1].Value if ($header -notmatch ('(?m)^modId\s*=\s*"' + [regex]::Escape($Id) + '"[ \t]*(?:#[^\r\n]*)?\r?$') -or - $header -notmatch '(?m)^version\s*=\s*"[^"\r\n]*\.119041"[ \t]*(?:#[^\r\n]*)?\r?$' -or - $Metadata -notmatch '(?m)^loaderVersion\s*=\s*"\[45,') { throw "Not a native Forge 45 candidate: $Id" } - $expected = @{ basepower = '2.4.11.119041'; basesteam = '2.2.12.119041'; baseelectric = '2.2.12.119041' } + $header -notmatch '(?m)^version\s*=\s*"[^"\r\n]*\.120011"[ \t]*(?:#[^\r\n]*)?\r?$' -or + $Metadata -notmatch '(?m)^loaderVersion\s*=\s*"\[47,') { throw "Not a native Forge 47 candidate: $Id" } + $expected = @{ basepower = '2.4.12.120011'; basesteam = '2.2.13.120011'; baseelectric = '2.2.13.120011' } if ($expected.ContainsKey($Id) -and $header -notmatch ('(?m)^version\s*=\s*"' + [regex]::Escape($expected[$Id]) + '"[ \t]*(?:#[^\r\n]*)?\r?$')) { throw "Unexpected native candidate version for $Id; expected $($expected[$Id])" } } function Assert-NativeLaunch([hashtable]$Environment, [hashtable]$Attributes) { - if ($Environment.MC_VERSION -ne '1.19.4' -or $Environment.FORGE_VERSION -ne '45.4.0' -or - $Environment.MCP_MAPPINGS -ne 'official_1.19.4' -or $Environment.MCP_VERSION -ne '20230314.122934' -or - $Environment.target -ne 'fmluserdevclient') { throw 'Regenerate the native 1.19.4 / Forge 45.4.0 official client launch.' } + if ($Environment.MC_VERSION -ne '1.20.1' -or $Environment.FORGE_VERSION -ne '47.4.10' -or + $Environment.MCP_MAPPINGS -ne 'official_1.20.1' -or $Environment.MCP_VERSION -ne '20230612.114412' -or + $Environment.target -ne 'fmluserdevclient') { throw 'Regenerate the native 1.20.1 / Forge 47.4.10 official client launch.' } $program = $Attributes['org.eclipse.jdt.launching.PROGRAM_ARGUMENTS'] - if ($program -notmatch '1\.19\.4-45\.4\.0' -or + if ($program -notmatch '1\.20\.1-47\.4\.10' -or $program -notmatch '--main cpw\.mods\.bootstraplauncher\.BootstrapLauncher\b' -or $program -notmatch '--launchTarget forgeclientuserdev\b' -or - $program -match '1\.(?:13\.2|14\.4|15\.2|16\.5|17\.1)|--(?:server|port|world)\b' -or + $program -match '1\.(?:13\.2|14\.4|15\.2|16\.5|17\.1|18\.2|19\.4)|--(?:server|port|world)\b' -or @([regex]::Matches($program, '--gameDir\s+\.(?=\s|$)')).Count -ne 1 -or @([regex]::Matches($program, '--gameDir\b')).Count -ne 1 -or $Attributes['org.eclipse.jdt.launching.MAIN_TYPE'] -ne 'net.minecraftforge.launcher.Main') { @@ -53,14 +53,14 @@ function Assert-NativeLaunch([hashtable]$Environment, [hashtable]$Attributes) { } } function Assert-NativeArchive([string]$Path) { - if ($Path -match '(?:forge|client-extra)-1\.(?:13\.2|14\.4|15\.2|16\.5|17\.1)|[\\/]PA11[345678][\\/]') { throw "Legacy runtime archive: $Path" } + if ($Path -match '(?:forge|client-extra)-1\.(?:13\.2|14\.4|15\.2|16\.5|17\.1|18\.2|19\.4)|[\\/]PA11[3456789][\\/]') { throw "Legacy runtime archive: $Path" } } function Quote-Argument([string]$Value) { '"' + [regex]::Replace([regex]::Replace($Value, '(\\*)"', '$1$1\"'), '(\\+)$', '$1$1') + '"' } $probe = Join-Path $project 'build/client-resource-probe/advantageclientresources-deobf.jar' $runtime = Join-Path $project ('run-client-resource-runs/' + [DateTime]::UtcNow.ToString('yyyyMMdd-HHmmss') + '-' + [guid]::NewGuid().ToString('N').Substring(0, 8)) -$inputReport = [ordered]@{ minecraft = '1.19.4'; forge = '45.4.0'; mappings = 'official_1.19.4'; mcp = '20230314.122934'; qualification = 'UNQUALIFIED'; output_source = $OutputSource; launch_profile = $LaunchProfile; require_extensions = [bool]$RequireExtensions; child_renderer_geometry = [bool]$ChildRendererGeometry } +$inputReport = [ordered]@{ minecraft = '1.20.1'; forge = '47.4.10'; mappings = 'official_1.20.1'; mcp = '20230612.114412'; qualification = 'UNQUALIFIED'; output_source = $OutputSource; launch_profile = $LaunchProfile; require_extensions = [bool]$RequireExtensions; child_renderer_geometry = [bool]$ChildRendererGeometry } $inputReport.machine_gui_layouts = [bool]$MachineGuiLayouts $phase = 'launch-preflight' New-Item -ItemType Directory -Path $runtime | Out-Null @@ -76,8 +76,8 @@ $inputReport.java = Get-Record $java $inputReport.launch = Get-Record (Join-Path $project $LaunchProfile) $inputReport.probe = Get-Record $probe $probeMetadata = Read-JarMetadata $probe -if ($probeMetadata -notmatch 'loaderVersion="\[45,46\)"' -or $probeMetadata -notmatch 'versionRange="\[1\.19\.4\]"' -or - $probeMetadata -notmatch 'versionRange="\[45\.4\.0\]"' -or $probeMetadata -notmatch 'versionRange="\[2\.4\.11\.119041\]"') { throw 'Rebuild the native 1.19 probe; do not substitute a legacy probe.' } +if ($probeMetadata -notmatch 'loaderVersion="\[47,48\)"' -or $probeMetadata -notmatch 'versionRange="\[1\.20\.1\]"' -or + $probeMetadata -notmatch 'versionRange="\[47\.4\.10\]"' -or $probeMetadata -notmatch 'versionRange="\[2\.4\.12\.120011\]"') { throw 'Rebuild the native 1.20.1 probe; do not substitute a legacy probe.' } Copy-Item -LiteralPath (Join-Path $project $LaunchProfile) -Destination (Join-Path $runtime 'launch.xml') $environment = @{} foreach ($map in $launch.launchConfiguration.mapAttribute) { @@ -108,7 +108,7 @@ $outputFiles = @(Get-ChildItem -LiteralPath $modOutput -Recurse -File | Sort-Obj if (@($outputFiles | Where-Object { $_.path -like '*.class' }).Count -eq 0) { throw 'Selected output has no compiled production classes.' } $outputFiles | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $runtime 'production-files.json') -Encoding utf8 $inputReport.production_files = Get-Record (Join-Path $runtime 'production-files.json') -if (-not $PowerCandidate) { $PowerCandidate = Join-Path $project 'build/libs-dev/basePower-2.4.11.119041-deobf.jar' } +if (-not $PowerCandidate) { $PowerCandidate = Join-Path $project 'build/libs-dev/basePower-2.4.12.120011-deobf.jar' } $PowerCandidate = (Resolve-Path -LiteralPath $PowerCandidate).Path Assert-NativeMetadata (Read-JarMetadata $PowerCandidate) 'basepower' $inputReport.power_candidate = Get-Record $PowerCandidate @@ -174,7 +174,7 @@ foreach ($archive in $archives) { $archives = $launchArchives $inputReport.archives = $archiveRecords $inputReport.runtime_candidates = $runtimeCandidates -if (-not ($archives -match 'forge-1\.19\.4-45\.4\.0\.jar$')) { throw 'Missing actual native mapped Forge runtime.' } +if (-not ($archives -match 'forge-1\.20\.1-47\.4\.10\.jar$')) { throw 'Missing actual native mapped Forge runtime.' } if ($RequireExtensions -and (-not $runtimeCandidates.ContainsKey('basesteam') -or -not $runtimeCandidates.ContainsKey('baseelectric'))) { throw 'Combined launch must explicitly contain both native expansion candidates.' } $arguments = @([regex]::Matches($attributes['org.eclipse.jdt.launching.PROGRAM_ARGUMENTS'], '"[^"]*"|\S+') | ForEach-Object { $_.Value.Trim('"') }) $vmArguments = @([regex]::Matches($attributes['org.eclipse.jdt.launching.VM_ARGUMENTS'], '"[^"]*"|\S+') | ForEach-Object { $_.Value.Trim('"') }) @@ -214,7 +214,7 @@ $resultPath = Join-Path $runtime 'client-resources.json' if (-not (Test-Path -LiteralPath $resultPath)) { throw "Client did not produce a result; inspect $runtime/logs" } $result = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json if ($result.status -ne 'PASS') { throw "Client resource check failed: $($result.error); inspect $runtime" } -if ($result.minecraft -ne '1.19.4' -or $result.forge -ne '45.4.0') { throw 'Result is not native 1.19.4 / Forge 45.4.0 evidence.' } +if ($result.minecraft -ne '1.20.1' -or $result.forge -ne '47.4.10') { throw 'Result is not native 1.20.1 / Forge 47.4.10 evidence.' } if ($MachineGuiLayouts -and $result.machine_gui_layout_status -ne 'PASS') { throw 'Machine GUI layouts did not pass; inspect the retained images and JSON.' } $expectedGuiTextChecks = if ($RequireExtensions) { 351 } else { 126 } if ($MachineGuiLayouts -and ($result.machine_gui_text_spec -ne 2 -or $result.machine_gui_text_status -ne 'PASS' -or diff --git a/test-rig/client-resources/test-launcher.ps1 b/test-rig/client-resources/test-launcher.ps1 index 70b6cf61..04b54611 100644 --- a/test-rig/client-resources/test-launcher.ps1 +++ b/test-rig/client-resources/test-launcher.ps1 @@ -76,33 +76,33 @@ if ($CrossVersionEvidenceRoots) { $native = @' modLoader="javafml" -loaderVersion="[45,)" # native Forge +loaderVersion="[47,)" # native Forge [[mods]] # mandatory header modId="basepower" # inline comment -version="2.4.11.119041" # native candidate +version="2.4.12.120011" # native candidate [[dependencies.basepower]] modId="minecraft" mandatory=true -versionRange="[1.19.4]" +versionRange="[1.20.1]" '@ Assert-NativeMetadata $native 'basepower' $checks++ -Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.11.119041','2.4.4.113021')) 'basepower' } -Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.11.119041','2.4.5.114041')) 'basepower' } -Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.11.119041','2.4.5.115021')) 'basepower' } -Assert-Throws { Assert-NativeMetadata ($native.Replace('[45,)','[36,)')) 'basepower' } -Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.11.119041','2.4.7.116051')) 'basepower' } -Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.11.119041','${version}')) 'basepower' } +Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.12.120011','2.4.4.113021')) 'basepower' } +Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.12.120011','2.4.5.114041')) 'basepower' } +Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.12.120011','2.4.5.115021')) 'basepower' } +Assert-Throws { Assert-NativeMetadata ($native.Replace('[47,)','[45,)')) 'basepower' } +Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.12.120011','2.4.7.116051')) 'basepower' } +Assert-Throws { Assert-NativeMetadata ($native.Replace('2.4.12.120011','${version}')) 'basepower' } Assert-Throws { Assert-NativeMetadata $native 'baseelectric' } Assert-Throws { Assert-NativeMetadata '' 'basepower' } foreach ($id in 'basesteam','baseelectric') { - $expansion = $native.Replace('basepower', $id).Replace('2.4.11.119041','2.2.12.119041') + $expansion = $native.Replace('basepower', $id).Replace('2.4.12.120011','2.2.13.120011') Assert-NativeMetadata $expansion $id $checks++ - Assert-Throws { Assert-NativeMetadata ($expansion.Replace('2.2.12.119041','2.2.6.115021')) $id } + Assert-Throws { Assert-NativeMetadata ($expansion.Replace('2.2.13.120011','2.2.6.115021')) $id } } -$environment = @{ MC_VERSION = '1.19.4'; FORGE_VERSION = '45.4.0'; MCP_MAPPINGS = 'official_1.19.4'; MCP_VERSION = '20230314.122934'; target = 'fmluserdevclient' } -$attributes = @{ 'org.eclipse.jdt.launching.PROGRAM_ARGUMENTS' = '--main cpw.mods.bootstraplauncher.BootstrapLauncher --cache D:\native\1.19.4-45.4.0 -- --launchTarget forgeclientuserdev --gameDir .'; 'org.eclipse.jdt.launching.MAIN_TYPE' = 'net.minecraftforge.launcher.Main' } +$environment = @{ MC_VERSION = '1.20.1'; FORGE_VERSION = '47.4.10'; MCP_MAPPINGS = 'official_1.20.1'; MCP_VERSION = '20230612.114412'; target = 'fmluserdevclient' } +$attributes = @{ 'org.eclipse.jdt.launching.PROGRAM_ARGUMENTS' = '--main cpw.mods.bootstraplauncher.BootstrapLauncher --cache D:\native\1.20.1-47.4.10 -- --launchTarget forgeclientuserdev --gameDir .'; 'org.eclipse.jdt.launching.MAIN_TYPE' = 'net.minecraftforge.launcher.Main' } Assert-NativeLaunch $environment $attributes $checks++ foreach ($key in 'MC_VERSION','FORGE_VERSION','MCP_MAPPINGS','MCP_VERSION','target') { @@ -118,7 +118,7 @@ foreach ($argument in '--server localhost','--port 25565','--gameDir D:\protecte $invalid = $attributes.Clone() $invalid['org.eclipse.jdt.launching.MAIN_TYPE'] = 'net.minecraft.client.main.Main' Assert-Throws { Assert-NativeLaunch $environment $invalid } -Assert-NativeArchive 'D:\native\forge-1.19.4-45.4.0.jar' +Assert-NativeArchive 'D:\native\forge-1.20.1-47.4.10.jar' $checks++ foreach ($path in 'D:\PA114\client.jar','D:\PA113\client.jar','D:\PA116\client.jar','D:\native\forge-1.16.5-36.2.34.jar','D:\native\forge-1.14.4-28.2.26.jar','D:\native\client-extra-1.13.2.jar') { Assert-Throws { Assert-NativeArchive $path } @@ -135,7 +135,7 @@ if ($StaticOnly) { return } $project = (Resolve-Path (Join-Path $PSScriptRoot '../..')).Path -$power = Join-Path $project 'build/libs-dev/basePower-2.4.11.119041-deobf.jar' +$power = Join-Path $project 'build/libs-dev/basePower-2.4.12.120011-deobf.jar' Assert-NativeMetadata (Read-JarMetadata $power) 'basepower' $checks++ [xml]$launch = Get-Content -LiteralPath (Join-Path $project 'runClientAllAdvantage.launch') -Raw diff --git a/test-rig/gradle.properties b/test-rig/gradle.properties index f9273f60..89188da2 100644 --- a/test-rig/gradle.properties +++ b/test-rig/gradle.properties @@ -1,12 +1,12 @@ org.gradle.jvmargs=-Xmx2G org.gradle.daemon=false -minecraft_version=1.19.4 -forge_version=45.4.0 +minecraft_version=1.20.1 +forge_version=47.4.10 mapping_channel=official -mapping_version=1.19.4 -mcp_version=20230314.122934 -harness_version=1.1.3.119041 -poweradvantage_deobf_sha256=512FDEC9275B33533EF773C110E6229E0F07268775FAD4B5942A15B68A9EB87D -poweradvantage_source_commit=c9995315e2aee9d9bffec8eb8b1191ad8a0faeb7 +mapping_version=1.20.1 +mcp_version=20230612.114412 +harness_version=1.1.4.120011 +poweradvantage_deobf_sha256=21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01 +poweradvantage_source_commit=83a3f028ffad220fe2f3cc4983a9340dde2295a8 poweradvantage_pin_status=SOURCE_AND_ARTIFACT_PINNED diff --git a/test-rig/migration/audit_native119_endurance.py b/test-rig/migration/audit_native1201_endurance.py similarity index 91% rename from test-rig/migration/audit_native119_endurance.py rename to test-rig/migration/audit_native1201_endurance.py index d283b453..119c6dff 100644 --- a/test-rig/migration/audit_native119_endurance.py +++ b/test-rig/migration/audit_native1201_endurance.py @@ -1,4 +1,4 @@ -"""Replay every station checkpoint from a completed 1.19.4 endurance run.""" +"""Replay every station checkpoint from a completed 1.20.1 endurance run.""" import argparse from collections import Counter @@ -10,14 +10,14 @@ from matrix import digest, write_json from native117 import require_disjoint from native117_broad import read_json -import native119 +import native1201 def replay(run, profile, specification): - report = read_json(run / "native119-endurance-results.json") - modes = ("fresh119", "retained-upgrade-native119") + report = read_json(run / "native1201-endurance-results.json") + modes = ("fresh1201", "retained-upgrade-native1201") require = endurance.require - require(report["status"] == "PASS" and report["minecraft"] == native119.MINECRAFT + require(report["status"] == "PASS" and report["minecraft"] == native1201.MINECRAFT and report["duration_seconds"] == 1800 and report["interval_seconds"] == 60 and report["retained_unchanged"] is True and set(report["profiles"]) == set(modes), "Expected a complete fresh and migrated 30-minute run") @@ -42,16 +42,16 @@ def replay(run, profile, specification): for mode in modes: runtime = run / mode station_path = runtime / "advantage-works-results" - native119.verify_runtime(runtime) + native1201.verify_runtime(runtime) require({jar.name: digest(jar) for jar in (runtime / "mods").glob("*.jar")} == expected_jars, mode + ": staged artifacts differ from the approved profile") for boot in ("endurance", "endurance-restart"): - native119.require_native_boot(runtime / f"console-{boot}.log") + native1201.require_native_boot(runtime / f"console-{boot}.log") rig = endurance.Rig(mode, runtime, None, None, definitions) def snapshot(station, label): document = read_json(station_path / f"{station}-checkpoint-{label}.json") - require(document["minecraft"] == native119.MINECRAFT and document["forge"] == native119.FORGE + require(document["minecraft"] == native1201.MINECRAFT and document["forge"] == native1201.FORGE and all(document["mods"].get(key) == value for key, value in mod_versions.items()), mode + ": checkpoint runtime differs from profile") return document @@ -91,7 +91,7 @@ def snapshot(station, label): results[mode] = dict(checkpoints=len(ledger), stationSnapshots=len(ledger) * len(endurance.CHECKED), setupToEndTicks=ticks, sampledTicks=sampled_ticks, sampledSeconds=sampled_seconds, sampledTicksPerSecond=sampled_ticks / sampled_seconds, outputs=dict(totals)) - return dict(status="PASS", inputReceiptSha256=digest(run / "native119-endurance-results.json"), profiles=results) + return dict(status="PASS", inputReceiptSha256=digest(run / "native1201-endurance-results.json"), profiles=results) def main(): diff --git a/test-rig/migration/fixtures/native119/fml.toml b/test-rig/migration/fixtures/native119/fml.toml deleted file mode 100644 index 05c12555..00000000 --- a/test-rig/migration/fixtures/native119/fml.toml +++ /dev/null @@ -1,6 +0,0 @@ -# Forge 45.4.0 dedicated-server defaults, captured without mod jars. -versionCheck = true -splashscreen = true -disableOptimizedDFU = true -defaultConfigPath = "defaultconfigs" -maxThreads = -1 diff --git a/test-rig/migration/fixtures/native1201/fml.toml b/test-rig/migration/fixtures/native1201/fml.toml new file mode 100644 index 00000000..81298385 --- /dev/null +++ b/test-rig/migration/fixtures/native1201/fml.toml @@ -0,0 +1,15 @@ +# Forge 47.4.10 defaults except for the external update check in disposable tests. +versionCheck = false +disableOptimizedDFU = true +defaultConfigPath = "defaultconfigs" +maxThreads = -1 +earlyWindowHeight = 480 +earlyWindowWidth = 854 +earlyWindowControl = true +earlyWindowFBScale = 1 +earlyWindowProvider = "fmlearlywindow" +earlyWindowMaximized = false +earlyWindowSkipGLVersions = [] +earlyWindowLogHelpMessage = true +earlyWindowSquir = false +earlyWindowShowCPU = false diff --git a/test-rig/migration/native117_broad_audit_fixtures.py b/test-rig/migration/native117_broad_audit_fixtures.py index 4e65c529..053386d7 100644 --- a/test-rig/migration/native117_broad_audit_fixtures.py +++ b/test-rig/migration/native117_broad_audit_fixtures.py @@ -15,7 +15,7 @@ LINE = Path(__file__).resolve().parents[3].name.removeprefix("PA") # This is a historical audit fixture, not an attestation about the active port. -if LINE in ("118", "119"): +if LINE not in ("113", "114", "115", "116", "117"): LINE = "117" diff --git a/test-rig/migration/native117_broad_result_audit.py b/test-rig/migration/native117_broad_result_audit.py index 96d6b0bc..08c5c07e 100644 --- a/test-rig/migration/native117_broad_result_audit.py +++ b/test-rig/migration/native117_broad_result_audit.py @@ -20,7 +20,7 @@ VERSIONS = {"113": ("1.13.2", "25.0.223"), "114": ("1.14.4", "28.2.26"), "115": ("1.15.2", "31.2.57"), "116": ("1.16.5", "36.2.34"), "117": ("1.17.1", "37.1.1"), "118": ("1.18.2", "40.3.0"), - "119": ("1.19.4", "45.4.0")} + "119": ("1.19.4", "45.4.0"), "1201": ("1.20.1", "47.4.10")} NATIVE117_LAUNCHERS = { "libraries/net/minecraftforge/forge/1.17.1-37.1.1/win_args.txt", "libraries/net/minecraftforge/forge/1.17.1-37.1.1/unix_args.txt", @@ -48,10 +48,20 @@ "libraries/cpw/mods/bootstraplauncher/1.1.2/bootstraplauncher-1.1.2.jar", "libraries/net/minecraft/server/1.19.4-20230314.122934/server-1.19.4-20230314.122934-extra.jar", } +NATIVE1201_LAUNCHERS = { + "libraries/net/minecraftforge/forge/1.20.1-47.4.10/win_args.txt", + "libraries/net/minecraftforge/forge/1.20.1-47.4.10/unix_args.txt", +} +NATIVE1201_REQUIRED_CODE = { + "libraries/net/minecraftforge/fmlloader/1.20.1-47.4.10/fmlloader-1.20.1-47.4.10.jar", + "libraries/cpw/mods/bootstraplauncher/1.1.2/bootstraplauncher-1.1.2.jar", + "libraries/net/minecraft/server/1.20.1-20230612.114412/server-1.20.1-20230612.114412-extra.jar", +} MODULAR_CODE = { "117": (NATIVE117_LAUNCHERS, NATIVE117_REQUIRED_CODE, ".117011"), "118": (NATIVE118_LAUNCHERS, NATIVE118_REQUIRED_CODE, ".118021"), "119": (NATIVE119_LAUNCHERS, NATIVE119_REQUIRED_CODE, ".119041"), + "1201": (NATIVE1201_LAUNCHERS, NATIVE1201_REQUIRED_CODE, ".120011"), } STATIONS = tuple(["W-%02d" % n for n in range(1, 5)] + ["S-%02d" % n for n in range(1, 9)] @@ -283,11 +293,13 @@ def log_evidence(evidence, path, line, phase, records): r"Advantage Works command failed") for row in text.splitlines(): require(not error.search(row), str(path) + ": native117 runtime error: " + row) - elif line in ("118", "119"): + elif line in ("118", "119", "1201"): if line == "118": from native118 import log_findings, MCP else: - from native119 import log_findings, MCP + from native1201 import log_findings, MCP + if line == "119": + MCP = "20230314.122934" require("with MCP " + MCP in text, str(path) + ": missing native" + line + " MCP identity") require("ThreadedAnvilChunkStorage: All dimensions are saved" in shutdown, str(path) + ": missing completed all-dimension shutdown") diff --git a/test-rig/migration/native119.py b/test-rig/migration/native1201.py similarity index 79% rename from test-rig/migration/native119.py rename to test-rig/migration/native1201.py index 472b7052..0a8e90b0 100644 --- a/test-rig/migration/native119.py +++ b/test-rig/migration/native1201.py @@ -1,9 +1,10 @@ -"""Run the 1.19.4 destination with exact, disposable server inputs.""" +"""Run the 1.20.1 destination with exact, disposable server inputs.""" import argparse import json import os import re +import tomllib from pathlib import Path from matrix import digest, stage as stage_server, write_json @@ -11,15 +12,15 @@ from native117_code import NativeLaunch, code_files -MINECRAFT = "1.19.4" -FORGE = "45.4.0" +MINECRAFT = "1.20.1" +FORGE = "47.4.10" FORGE_VERSION = f"{MINECRAFT}-{FORGE}" -MCP = "20230314.122934" +MCP = "20230612.114412" RIG = Path(__file__).resolve().parents[1] LAUNCHER = f"libraries/net/minecraftforge/forge/{FORGE_VERSION}/" + ( "win_args.txt" if os.name == "nt" else "unix_args.txt") -INVENTORY = "native119-code-inventory.json" -FML_DEFAULTS = RIG / "migration/fixtures/native119/fml.toml" +INVENTORY = "native1201-code-inventory.json" +FML_DEFAULTS = RIG / "migration/fixtures/native1201/fml.toml" NETTY_PROBES = { "direct buffer constructor: unavailable": "java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled", "jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable": ( @@ -59,7 +60,7 @@ def require_boot_identity(path): for marker in (f"Starting minecraft server version {MINECRAFT}", f"Forge mod loading, version {FORGE}, for MC {MINECRAFT} with MCP {MCP}", "Done ("): if marker not in text: - raise AssertionError("Missing native 1.19.4 startup witness: " + marker) + raise AssertionError("Missing native 1.20.1 startup witness: " + marker) def require_native_boot(path): @@ -69,7 +70,7 @@ def require_native_boot(path): def seal(seed, receipt): if receipt.exists() or not (seed / LAUNCHER).is_file(): - raise ValueError("Supply an installed 1.19.4 server and a new inventory path") + raise ValueError("Supply an installed 1.20.1 server and a new inventory path") require_disjoint(receipt, seed) write_json(receipt, {"forge": FORGE_VERSION, "files": code_files(seed)}) @@ -80,7 +81,7 @@ def read_target(profile, seed, inventory, inventory_hash): if (data.get("minecraftVersion") != MINECRAFT or data.get("forge", {}).get("version") != FORGE_VERSION or data.get("mode") != "packaged" or data.get("portStatus") != "PORTED_UNQUALIFIED" or data.get("qualificationStatus") != "UNQUALIFIED"): - raise ValueError("Use a pinned, unqualified Forge 45.4.0 destination profile") + raise ValueError("Use a pinned, unqualified Forge 47.4.10 destination profile") if digest(inventory) != inventory_hash.upper(): raise AssertionError("Forge server inventory hash changed") code = json.loads(inventory.read_text(encoding="utf-8")) @@ -90,10 +91,10 @@ def read_target(profile, seed, inventory, inventory_hash): for mod in data["mods"]: jar = (RIG / mod["path"]).resolve() identity = mod["id"] - if (identity in entries or not mod["version"].endswith(".119041") + if (identity in entries or not mod["version"].endswith(".120011") or mod["file"] != jar.name or "deobf" in jar.name or not re.fullmatch("[A-Fa-f0-9]{64}", mod["sha256"])): - raise ValueError(f"Invalid packaged 1.19.4 mod pin: {identity}") + raise ValueError(f"Invalid packaged 1.20.1 mod pin: {identity}") if digest(jar) != mod["sha256"].upper(): raise AssertionError(f"Pinned mod changed: {jar}") jar_identity(jar, identity, mod["version"]) @@ -140,15 +141,37 @@ def verify_runtime(runtime): def prepare_fml_defaults(runtime): - # Avoid Forge's first-write/file-watcher race without touching imported settings. + # Avoid Forge's first-write race and keep external update services out of the test. config = runtime / "config/fml.toml" config.parent.mkdir(exist_ok=True) try: with config.open("xb") as output: output.write(FML_DEFAULTS.read_bytes()) except FileExistsError: + original = config.read_bytes() + text = original.decode("utf-8") + settings = tomllib.loads(text) + if settings.get("versionCheck") is False: + return + if "versionCheck" in settings: + updated, count = re.subn(r"(?m)^([ \t]*versionCheck[ \t]*=[ \t]*)true(?=[ \t]*(?:#|\r?$))", + r"\g<1>false", text, count=1) + if count != 1: + raise ValueError("Cannot isolate the update check in the copied Forge configuration") + else: + updated = "versionCheck = false\n" + text + if tomllib.loads(updated) != dict(settings, versionCheck=False): + raise AssertionError("A setting other than the external Forge update check would change") + backup = runtime / "fml-pre-qualification.toml" + with backup.open("xb") as output: + output.write(original) + config.write_bytes(updated.encode("utf-8")) + write_json(runtime / "native1201-fml-defaults.json", + {"sha256": digest(config), "originalSha256": digest(backup), "forge": FORGE_VERSION, + "versionCheck": False}) return - write_json(runtime / "native119-fml-defaults.json", {"sha256": digest(FML_DEFAULTS), "forge": FORGE_VERSION}) + write_json(runtime / "native1201-fml-defaults.json", + {"sha256": digest(FML_DEFAULTS), "forge": FORGE_VERSION, "versionCheck": False}) class Server(NativeLaunch): @@ -175,7 +198,7 @@ def close(self): def main(): - parser = argparse.ArgumentParser(description="Seal a Forge 45.4.0 test server's executable inputs.") + parser = argparse.ArgumentParser(description="Seal a Forge 47.4.10 test server's executable inputs.") parser.add_argument("--seed", type=Path, required=True) parser.add_argument("--inventory", type=Path, required=True) args = parser.parse_args() diff --git a/test-rig/migration/native119_actors.py b/test-rig/migration/native1201_actors.py similarity index 88% rename from test-rig/migration/native119_actors.py rename to test-rig/migration/native1201_actors.py index 94f9dff6..600aa912 100644 --- a/test-rig/migration/native119_actors.py +++ b/test-rig/migration/native1201_actors.py @@ -1,4 +1,4 @@ -"""Check retained player and dimension fixtures on the pinned Forge 45 server.""" +"""Check retained player and dimension fixtures on the pinned Forge 47 server.""" import argparse from functools import partial @@ -11,7 +11,7 @@ from native117_actors import run_route from native117_broad import read_json from native117_stopped_entities import audit_stopped -import native119 +import native1201 def main(): @@ -33,22 +33,22 @@ def main(): before = fingerprint(source) if Path(approved["source"]).resolve() != source or approved["sourceFingerprint"] != before: raise AssertionError("Historical fixture no longer matches its approved source") - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) with socket.socket() as port: port.bind(("127.0.0.1", args.port)) output.mkdir() result = dict(status="RUNNING", kind=args.kind, source=str(source), realClientLogin="NOT_TESTED", fixtureReceiptSha256=digest(args.fixture_receipt), profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), checks={}) - report = output / "native119-actors-results.json" + report = output / "native1201-actors-results.json" write_json(report, result) try: args.target_manifest = args.profile result["checks"] = run_route( - source, output / "server", target, args, stage=native119.stage, server_type=native119.Server, - stop_audit=partial(audit_stopped, minecraft_version=native119.MINECRAFT, data_version=3337, + source, output / "server", target, args, stage=native1201.stage, server_type=native1201.Server, + stop_audit=partial(audit_stopped, minecraft_version=native1201.MINECRAFT, data_version=3465, stopping_phase="ServerStoppingEvent"), - check_log=native119.require_native_boot, minecraft=native119.MINECRAFT) + check_log=native1201.require_native_boot, minecraft=native1201.MINECRAFT) result["status"] = "PASS" if all(c["status"] == "PASS" for c in result["checks"].values()) else "FAIL" except Exception: result.update(status="FAIL", error=traceback.format_exc()) diff --git a/test-rig/migration/native119_broad.py b/test-rig/migration/native1201_broad.py similarity index 84% rename from test-rig/migration/native119_broad.py rename to test-rig/migration/native1201_broad.py index 68a94423..7daf92e6 100644 --- a/test-rig/migration/native119_broad.py +++ b/test-rig/migration/native1201_broad.py @@ -1,4 +1,4 @@ -"""Commission and restart all 21 Works stations with the pinned 1.19.4 jars.""" +"""Commission and restart all 21 Works stations with the pinned 1.20.1 jars.""" import argparse from pathlib import Path @@ -8,7 +8,7 @@ from matrix import digest, write_json from native117 import output_path, require_disjoint from native117_broad import campaign_document, read_json, run_profile -import native119 +import native1201 def freeze_mods(entries, destination): @@ -35,23 +35,23 @@ def main(): if not 1 <= args.run_seconds <= 60 or not 1024 <= args.port < 65535: parser.error("Bounded run duration and unprivileged consecutive ports required") output = output_path(args.output) - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) if "basemetals" not in target[2]: raise ValueError("Use the complete profile; the decoupled profile is derived from it") for path in (args.profile, args.seed, args.inventory, *(item["path"] for item in target[2].values())): require_disjoint(output, path) - definition = native119.RIG / "src/main/resources/assets/advantageworkstest/works/works-1.13.2.json" + definition = native1201.RIG / "src/main/resources/assets/advantageworkstest/works/works-1.13.2.json" stations = read_json(definition)["stations"] if len(stations) != 21: raise AssertionError("The complete 21-bay specification is required") output.mkdir(parents=True) - manifest = output / "target119.json" + manifest = output / "target1201.json" seed, code, entries = target entries = freeze_mods(entries, output / "pinned-inputs") target = seed, code, entries - write_json(manifest, {"target119": { - "seed": str(seed), "launcher": native119.LAUNCHER, - "launcher_sha256": digest(seed / native119.LAUNCHER), "serverCode": code, + write_json(manifest, {"target1201": { + "seed": str(seed), "launcher": native1201.LAUNCHER, + "launcher_sha256": digest(seed / native1201.LAUNCHER), "serverCode": code, "jars": [{**item, "path": str(item["path"])} for item in entries.values()], }}) runner = output / "runner-source.py" @@ -59,14 +59,14 @@ def main(): proof = dict(profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), stationDefinitionSha256=digest(definition), runnerSha256=digest(runner), targetManifest=str(manifest), targetManifestSha256=digest(manifest), - minecraft=native119.MINECRAFT) + minecraft=native1201.MINECRAFT) names = ("packaged-current", "packaged-decoupled") results = {} - report = output / "native119-broad-results.json" + report = output / "native1201-broad-results.json" for index, name in enumerate(names): write_json(report, campaign_document(names, results, proof, finished=False)) try: - results[name] = run_profile(args, None, output, name, args.port + index, stations, native118_target=target, native_adapter=native119) + results[name] = run_profile(args, None, output, name, args.port + index, stations, native118_target=target, native_adapter=native1201) except Exception: results[name] = dict(status="FAIL", profile=name, error=traceback.format_exc()) print(name, results[name]["status"], flush=True) diff --git a/test-rig/migration/native119_endurance.py b/test-rig/migration/native1201_endurance.py similarity index 90% rename from test-rig/migration/native119_endurance.py rename to test-rig/migration/native1201_endurance.py index 776023f7..69d559b3 100644 --- a/test-rig/migration/native119_endurance.py +++ b/test-rig/migration/native1201_endurance.py @@ -1,4 +1,4 @@ -"""Run the measured Works feed, conservation and cold-restart protocol on 1.19.4.""" +"""Run the measured Works feed, conservation and cold-restart protocol on 1.20.1.""" import argparse from collections import Counter @@ -11,11 +11,11 @@ from native117 import native_normalized, output_path, require_disjoint from native117_broad import read_json from native117_endurance import NativeEnduranceRig, configure_new_fresh_fixture, prove_fresh_fixture_before_build -import native119 +import native1201 class Rig(NativeEnduranceRig): - server_type = native119.Server + server_type = native1201.Server def main(): @@ -29,32 +29,32 @@ def main(): args = parser.parse_args() endurance.require(args.seconds >= 60 and args.seconds % 60 == 0, "Use whole one-minute batches") root = output_path(args.output) - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) for protected in (args.profile, args.seed, args.inventory, *(item["path"] for item in target[2].values())): require_disjoint(root, protected) source_before = None if args.retained: require_disjoint(root, args.retained) - prior = read_json(args.retained / "native119-legacy-world-results.json") + prior = read_json(args.retained / "native1201-legacy-world-results.json") if (prior["status"] != "PASS" or prior["profileSha256"] != digest(args.profile) or prior["inventorySha256"] != digest(args.inventory) or digest(args.retained / "migration-restarted.json") != prior["phases"]["restarted"]["snapshotSha256"]): raise AssertionError("Retained input does not match the passing pinned migration") source_before = fingerprint(args.retained / WORLD) - spec = native119.RIG / "src/main/resources/assets/advantageworkstest/works/works-1.13.2.json" + spec = native1201.RIG / "src/main/resources/assets/advantageworkstest/works/works-1.13.2.json" definitions = {row["id"]: row for row in read_json(spec)["stations"]} - report = dict(status="RUNNING", minecraft=native119.MINECRAFT, duration_seconds=args.seconds, + report = dict(status="RUNNING", minecraft=native1201.MINECRAFT, duration_seconds=args.seconds, interval_seconds=60, profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), stationDefinitionSha256=digest(spec), active_stations=endurance.ACTIVE, checked_stations=endurance.CHECKED, profiles={}, retained=str(args.retained) if args.retained else None) - receipt = root / "native119-endurance-results.json" + receipt = root / "native1201-endurance-results.json" write_json(receipt, report) rigs = [] try: - cases = (("fresh119", None), ("retained-upgrade-native119", args.retained)) if args.retained else (("fresh119", None),) + cases = (("fresh1201", None), ("retained-upgrade-native1201", args.retained)) if args.retained else (("fresh1201", None),) for index, (name, source) in enumerate(cases): runtime = root / name - launcher = native119.stage(runtime, target, args.port + index) + launcher = native1201.stage(runtime, target, args.port + index) rig = Rig(name, runtime, args.java17, launcher, definitions) rigs.append(rig) if source: @@ -134,7 +134,7 @@ def main(): for rig in rigs: try: rig.shutdown() - native119.verify_runtime(rig.runtime) + native1201.verify_runtime(rig.runtime) except Exception as error: report.update(status="FAIL", shutdown_or_audit_error=repr(error)) if args.retained: diff --git a/test-rig/migration/native119_legacy_world.py b/test-rig/migration/native1201_legacy_world.py similarity index 91% rename from test-rig/migration/native119_legacy_world.py rename to test-rig/migration/native1201_legacy_world.py index 6a82494d..3af7d589 100644 --- a/test-rig/migration/native119_legacy_world.py +++ b/test-rig/migration/native1201_legacy_world.py @@ -1,4 +1,4 @@ -"""Compare original and released legacy fixtures against live and saved 1.19.4 state.""" +"""Compare original and released legacy fixtures against live and saved 1.20.1 state.""" import argparse from pathlib import Path @@ -11,8 +11,8 @@ from native117_broad import read_json from native117_commands import native from native117_legacy_world import turbine -import native119 -import native119_saved +import native1201 +import native1201_saved def portable(hashes): @@ -20,7 +20,7 @@ def portable(hashes): def operate(runtime, frozen, target, java, port, positions, expected): - launcher = native119.stage(runtime, target, port) + launcher = native1201.stage(runtime, target, port) for path in (WORLD, "config"): shutil.copytree(frozen / path, runtime / path) shutil.copy2(frozen / "migration-fixture.json", runtime / "migration-fixture.json") @@ -28,7 +28,7 @@ def operate(runtime, frozen, target, java, port, positions, expected): jobs = (("sourceChest", "destination", "dirt", "dirt", 8), ("steamCrusher", "steamCrusher", "stone", "cobblestone", 1), ("electricFurnace", "electricFurnace", "iron_ore", "iron_ingot", 1)) - server = native119.Server(runtime, java, launcher, "operation") + server = native1201.Server(runtime, java, launcher, "operation") try: for source, _, item, _, count in jobs: x, y, z = positions[source] @@ -79,10 +79,10 @@ def main(): if before != portable(previous["sourceFingerprint"]): raise AssertionError("Legacy source changed since the previous run") output = output_path(args.output) - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) for protected in (source, args.profile, args.fixture, args.seed, args.inventory): require_disjoint(output, protected) - launcher = native119.stage(output, target, args.port) + launcher = native1201.stage(output, target, args.port) shutil.copytree(source / WORLD, output / WORLD) shutil.copytree(source / "config", output / "config") if fingerprint(source / WORLD) != fingerprint(output / WORLD): @@ -92,11 +92,11 @@ def main(): result = dict(status="RUNNING", source=str(source), sourceFingerprint=before, priorReceiptSha256=digest(args.prior_run), profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), phases={}) - report = output / "native119-legacy-world-results.json" + report = output / "native1201-legacy-world-results.json" try: saves = {} for phase in ("converted", "restarted"): - server = native119.Server(output, args.java17, launcher, phase) + server = native1201.Server(output, args.java17, launcher, phase) try: server.snapshot(phase) server.send("save-all flush") @@ -106,8 +106,8 @@ def main(): snapshot = output / f"migration-{phase}.json" rows = read_json(snapshot) verify_snapshot(expected, rows) - saves[phase] = native119_saved.capture(output, phase, rows) - observed = turbine(output / WORLD, positions["hydroGenerator"], data_version=native119_saved.DATA_VERSION) + saves[phase] = native1201_saved.capture(output, phase, rows) + observed = turbine(output / WORLD, positions["hydroGenerator"], data_version=native1201_saved.DATA_VERSION) if observed != dict(expected["turbine"], id="baseelectric:hydroturbine"): raise AssertionError("Saved turbine identity, position or parent changed") result["phases"][phase] = dict(status="PASS", witnesses=len(rows), turbine=observed, diff --git a/test-rig/migration/native119_machines.py b/test-rig/migration/native1201_machines.py similarity index 80% rename from test-rig/migration/native119_machines.py rename to test-rig/migration/native1201_machines.py index e6a2e59f..3dca463f 100644 --- a/test-rig/migration/native119_machines.py +++ b/test-rig/migration/native1201_machines.py @@ -1,4 +1,4 @@ -"""Exercise 1.19.4 machines using the historical lifecycle and harvest oracles.""" +"""Exercise 1.20.1 machines using the historical lifecycle and harvest oracles.""" import argparse from pathlib import Path @@ -12,42 +12,42 @@ from native117_lifecycle import NativeLifecycleRun, authorize_lifecycle, exercise, read_json from native117_oil import NativeOilRun, exercise as exercise_oil, fixtures as oil_fixtures from native117_readiness import await_ready -import native119 +import native1201 MINERALOGY = { "id": "mineralogy", - "version": "6.1.4.119041", - "sourceRef": "84222a0f129c086fd5ddcdb4244468f50ac0d4d1", - "file": "Mineralogy-6.1.4.119041.jar", - "sha256": "0E197D92B74F8466F35B31357E12629649EA58FF655CEFDF0D1991BE72DDA8A6", + "version": "6.1.4.120011", + "sourceRef": "3826585128a53dbbd94e05e025ddb32a693ae428", + "file": "Mineralogy-6.1.4.120011.jar", + "sha256": "1172C7FF424BCE10E3EAC7A790353CAB35E5A5F06EBB019B31BED05B90ED8A5F", } class LifecycleRun(NativeLifecycleRun): - minecraft = native119.MINECRAFT + minecraft = native1201.MINECRAFT max_ticket_distance = 12 - require_boot = staticmethod(native119.require_native_boot) + require_boot = staticmethod(native1201.require_native_boot) def open_server(self, label): - return native119.Server(self.runtime, self.java, self.launcher, label) + return native1201.Server(self.runtime, self.java, self.launcher, label) class OilRun(NativeOilRun): - expected_launcher = native119.LAUNCHER - require_boot = staticmethod(native119.require_native_boot) + expected_launcher = native1201.LAUNCHER + require_boot = staticmethod(native1201.require_native_boot) def open_server(self, label): - return native119.Server(self.runtime, self.java, self.launcher, label) + return native1201.Server(self.runtime, self.java, self.launcher, label) def harvest(runtime, java, launcher, report, progress): mark_runtime(runtime) for label in ("exercise", "restored"): - server = native119.Server(runtime, java, launcher, label) + server = native1201.Server(runtime, java, launcher, label) try: server.send("forceload add 1198 1022 1202 1026") ready = await_ready(server, runtime, HARVEST_CHUNKS, "harvest-" + label, - minecraft=native119.MINECRAFT) + minecraft=native1201.MINECRAFT) server.send("advharvest " + label) server.wait("ADVHARVEST COMPLETE " + label, 120) document = read_json(runtime / "advantage-works-results" / f"native-harvest-{label}.json") @@ -55,7 +55,7 @@ def harvest(runtime, java, launcher, report, progress): or document["worldTime"] < ready["completedWorldTime"]): raise AssertionError("Harvest preceded native chunk/entity readiness") report[label] = {"observation": document, "readiness": ready} - require_checks(document, label, minecraft=native119.MINECRAFT) + require_checks(document, label, minecraft=native1201.MINECRAFT) require_isolation(document) server.send("save-all flush") server.wait("Saved the game", 30) @@ -74,7 +74,7 @@ def main(): parser.add_argument("--campaign", choices=("lifecycle", "harvest", "oil"), required=True) parser.add_argument("--mineralogy-jar", type=Path, help="Include the pinned Mineralogy build in the oil test") args = parser.parse_args() - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) if args.mineralogy_jar: jar = args.mineralogy_jar.resolve() if args.campaign != "oil" or jar.name != MINERALOGY["file"] or digest(jar) != MINERALOGY["sha256"]: @@ -88,9 +88,9 @@ def main(): Path(__file__).with_name(f"native117_{args.campaign}.py")] helper_hashes = {path.name: digest(path) for path in helpers} seed_hashes = fingerprint(target[0]) - launcher = native119.stage(output, target, args.port) - path = output / f"native119-{args.campaign}-results.json" - report = dict(status="RUNNING", minecraft=native119.MINECRAFT, forge=native119.FORGE, + launcher = native1201.stage(output, target, args.port) + path = output / f"native1201-{args.campaign}-results.json" + report = dict(status="RUNNING", minecraft=native1201.MINECRAFT, forge=native1201.FORGE, profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), javaSha256=digest(args.java17), helperSha256=helper_hashes) @@ -116,7 +116,7 @@ def progress(values): write_json(output / "lifecycle-fixture.json", definition) authorize_lifecycle(output) runner = LifecycleRun(output, args.java17, launcher, definition) - result = exercise(runner, "fresh119", progress) + result = exercise(runner, "fresh1201", progress) report.update(status=result["status"], observations=result) except Exception as error: report.update(status="FAIL", failure=repr(error), traceback=traceback.format_exc()) @@ -125,7 +125,7 @@ def progress(values): try: if runner is not None: runner.close() - native119.verify_runtime(output) + native1201.verify_runtime(output) report["seedUnchanged"] = fingerprint(target[0]) == seed_hashes report["helpersUnchanged"] = {path.name: digest(path) for path in helpers} == helper_hashes if not report["seedUnchanged"] or not report["helpersUnchanged"]: diff --git a/test-rig/migration/native119_modern_upgrade.py b/test-rig/migration/native1201_modern_upgrade.py similarity index 79% rename from test-rig/migration/native119_modern_upgrade.py rename to test-rig/migration/native1201_modern_upgrade.py index c8aa4ff0..288c3303 100644 --- a/test-rig/migration/native119_modern_upgrade.py +++ b/test-rig/migration/native1201_modern_upgrade.py @@ -1,4 +1,4 @@ -"""Load and operate a stopped, already-qualified 1.18.2 save on 1.19.4.""" +"""Load and operate a stopped, already-qualified 1.19.4 save on 1.20.1.""" import argparse from pathlib import Path @@ -8,9 +8,9 @@ from native117 import native_normalized, output_path, require_disjoint from native117_legacy_world import turbine from native117_lifecycle import read_json -import native119 -from native119_legacy_world import operate -import native119_saved +import native1201 +from native1201_legacy_world import operate +import native1201_saved def main(): @@ -22,9 +22,9 @@ def main(): parser.add_argument("--port", type=int, required=True) args = parser.parse_args() source = args.source.resolve() - prior = source / "native118-legacy-world-results.json" + prior = source / "native119-legacy-world-results.json" if digest(prior) != args.receipt_sha256.upper(): - raise AssertionError("The protected 1.18.2 receipt changed") + raise AssertionError("The protected 1.19.4 receipt changed") receipt = read_json(prior) if receipt["status"] != "PASS" or not receipt["sourceUnchanged"]: raise AssertionError("Source lacks a passing independent migration receipt") @@ -41,25 +41,25 @@ def main(): before = fingerprint(source) positions = {row["name"]: [row["x"], row["y"], row["z"]] for row in read_json(source / "migration-fixture.json")} - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) output = output_path(args.output) for path in (source, args.profile, args.seed, args.inventory, *(item["path"] for item in target[2].values())): require_disjoint(output, path) - launcher = native119.stage(output, target, args.port) + launcher = native1201.stage(output, target, args.port) for path in (WORLD, "config"): shutil.copytree(source / path, output / path) if fingerprint(source / WORLD) != fingerprint(output / WORLD): - raise AssertionError("The staged 1.18.2 save differs from the source") + raise AssertionError("The staged 1.19.4 save differs from the source") shutil.copy2(source / "migration-fixture.json", output / "migration-fixture.json") (output / "advantage-migration.allow").touch() - result = dict(status="RUNNING", minecraft=native119.MINECRAFT, forge=native119.FORGE, + result = dict(status="RUNNING", minecraft=native1201.MINECRAFT, forge=native1201.FORGE, source=str(source), sourceReceiptSha256=digest(prior), sourceFingerprint=before, profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), phases={}) - result_path = output / "native119-modern-upgrade-results.json" + result_path = output / "native1201-modern-upgrade-results.json" try: for label in ("converted", "restarted"): - server = native119.Server(output, args.java17, launcher, label) + server = native1201.Server(output, args.java17, launcher, label) try: server.snapshot(label) server.send("save-all flush") @@ -70,12 +70,12 @@ def main(): comparison = compare(historical, snapshot, native_normalized) result["phases"][label] = comparison if comparison["status"] != "PASS": - raise AssertionError("The native 1.18.2 witnesses changed in " + label) - saved = native119_saved.capture(output, label, read_json(snapshot)) + raise AssertionError("The native 1.19.4 witnesses changed in " + label) + saved = native1201_saved.capture(output, label, read_json(snapshot)) observed = turbine(output / WORLD, positions["hydroGenerator"], - data_version=native119_saved.DATA_VERSION) + data_version=native1201_saved.DATA_VERSION) if observed != phase["turbine"]: - raise AssertionError("The saved 1.18.2 turbine changed") + raise AssertionError("The saved 1.19.4 turbine changed") result["phases"][label].update(serialized=saved, turbine=observed, snapshotSha256=digest(snapshot)) write_json(result_path, result) diff --git a/test-rig/migration/native119_networks.py b/test-rig/migration/native1201_networks.py similarity index 87% rename from test-rig/migration/native119_networks.py rename to test-rig/migration/native1201_networks.py index 466a5208..ec302f77 100644 --- a/test-rig/migration/native119_networks.py +++ b/test-rig/migration/native1201_networks.py @@ -1,4 +1,4 @@ -"""Run the original partial-network, bridge and native interop oracles on Forge 45.""" +"""Run the original partial-network, bridge and native interop oracles on Forge 47.""" import argparse from pathlib import Path @@ -14,8 +14,8 @@ from native117_partial import exercise_bridge, exercise_partial from native117_readiness import await_ready from native117_ticket_networks import NativeTicketExtendedRun -import native119 -from native119_machines import LifecycleRun +import native1201 +from native1201_machines import LifecycleRun class PartialRun(NativeTicketExtendedRun, LifecycleRun): @@ -29,11 +29,11 @@ def interop(runtime, launcher, java, progress): mark_runtime(runtime) observations = {} for phase in ("exercise", "restored"): - server = native119.Server(runtime, java, launcher, phase) + server = native1201.Server(runtime, java, launcher, phase) try: server.send("forceload add 1023 1023 1100 1030") ready = await_ready(server, runtime, (63, 63, 68, 64), "interop-" + phase, - minecraft=native119.MINECRAFT) + minecraft=native1201.MINECRAFT) server.send("advinterop " + phase) server.wait("ADVINTEROP COMPLETE " + phase, 120) report = read_json(runtime / "advantage-works-results" / f"native-interop-{phase}.json") @@ -56,16 +56,16 @@ def main(): parser.add_argument("--port", type=int, required=True) parser.add_argument("--campaign", choices=("partial", "bridge", "extended", "interop"), required=True) args = parser.parse_args() - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) runtime = output_path(args.output) for path in (args.profile, args.seed, args.inventory, *(item["path"] for item in target[2].values())): require_disjoint(runtime, path) protected = fingerprint(target[0]) - launcher = native119.stage(runtime, target, args.port) - report = dict(status="RUNNING", minecraft=native119.MINECRAFT, forge=native119.FORGE, + launcher = native1201.stage(runtime, target, args.port) + report = dict(status="RUNNING", minecraft=native1201.MINECRAFT, forge=native1201.FORGE, profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), javaSha256=digest(args.java17), runnerSha256=digest(Path(__file__))) - receipt = runtime / f"native119-{args.campaign}-results.json" + receipt = runtime / f"native1201-{args.campaign}-results.json" def progress(value): report["observations"] = value @@ -94,7 +94,7 @@ def progress(value): try: if runner is not None: runner.close() - native119.verify_runtime(runtime) + native1201.verify_runtime(runtime) report["seedUnchanged"] = fingerprint(target[0]) == protected if not report["seedUnchanged"]: raise AssertionError("Protected server seed changed during the test") diff --git a/test-rig/migration/native119_recipes.py b/test-rig/migration/native1201_recipes.py similarity index 78% rename from test-rig/migration/native119_recipes.py rename to test-rig/migration/native1201_recipes.py index ca81ff6c..b4bf7d81 100644 --- a/test-rig/migration/native119_recipes.py +++ b/test-rig/migration/native1201_recipes.py @@ -1,4 +1,4 @@ -"""Run recipe discovery and survival progression against the 1.19.4 player jars.""" +"""Run recipe discovery and survival progression against the 1.20.1 player jars.""" import argparse from pathlib import Path @@ -6,25 +6,25 @@ from matrix import digest, fingerprint, write_json from native117 import output_path, require_disjoint from native117_recipes import MOD_COUNTS, RecipePruning, progression_campaign, recipe_fixture, unlock_campaign -import native119 +import native1201 -class RecipeServer(RecipePruning, native119.Server): +class RecipeServer(RecipePruning, native1201.Server): @staticmethod def errors(text): - return native119.log_findings(text)[0] + return native1201.log_findings(text)[0] class Engine: - version = (native119.MINECRAFT, native119.FORGE) + version = (native1201.MINECRAFT, native1201.FORGE) pack_format = 9 - server = native119.Server + server = native1201.Server recipe_server = RecipeServer - result_name = "native119-recipes-results.json" + result_name = "native1201-recipes-results.json" @staticmethod def stage(runtime, target, port, campaign): - launcher = native119.stage(runtime, target, port) + launcher = native1201.stage(runtime, target, port) (runtime / ("advantage-recipes.allow" if campaign == "unlock" else "advantage-progression.allow")).touch() if campaign == "progression": (runtime / "advantage-works.allow").touch() @@ -40,14 +40,14 @@ def main(): parser.add_argument("--port", type=int, default=25650) parser.add_argument("--campaign", choices=("all", "unlock", "progression"), default="all") args = parser.parse_args() - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) root = output_path(args.output) for path in (args.profile, args.seed, args.inventory, *(item["path"] for item in target[2].values())): require_disjoint(root, path) definition, sources = recipe_fixture([item["path"] for item in target[2].values()]) entry = {"jars": [{**item, "path": str(item["path"])} for item in target[2].values()]} before = fingerprint(target[0]) - report = dict(status="RUNNING", minecraft=native119.MINECRAFT, forge=native119.FORGE, campaign=args.campaign, + report = dict(status="RUNNING", minecraft=native1201.MINECRAFT, forge=native1201.FORGE, campaign=args.campaign, profileSha256=digest(args.profile), inventorySha256=digest(args.inventory), javaSha256=digest(args.java17), target_jars=entry["jars"], recipe_inventory=MOD_COUNTS, unlock_boots=[], progression_cases=[]) @@ -56,11 +56,11 @@ def main(): if args.campaign in ("all", "unlock"): unlock_campaign(root, target, entry, args.java17, args.port, definition, report, engine=Engine) if len(report["unlock_boots"]) != 5: - raise AssertionError("Incomplete 1.19.4 unlock campaign") + raise AssertionError("Incomplete 1.20.1 unlock campaign") if args.campaign in ("all", "progression"): progression_campaign(root, target, entry, args.java17, args.port, report, engine=Engine) if len(report["progression_cases"]) != 18: - raise AssertionError("Incomplete 1.19.4 progression campaign") + raise AssertionError("Incomplete 1.20.1 progression campaign") report["status"] = "PASS" except BaseException as failure: report.update(status="FAIL", error=repr(failure)) diff --git a/test-rig/migration/native119_respawn.py b/test-rig/migration/native1201_respawn.py similarity index 81% rename from test-rig/migration/native119_respawn.py rename to test-rig/migration/native1201_respawn.py index 79ec3353..09f37a04 100644 --- a/test-rig/migration/native119_respawn.py +++ b/test-rig/migration/native1201_respawn.py @@ -1,4 +1,4 @@ -"""Run the retained twelve-case native death and respawn oracle on Forge 45.""" +"""Run the retained twelve-case native death and respawn oracle on Forge 47.""" import argparse from pathlib import Path @@ -6,7 +6,7 @@ from matrix import digest from native117 import output_path, require_disjoint from native117_respawn import read_json, run -import native119 +import native1201 def main(): @@ -27,10 +27,10 @@ def main(): source = Path(record["path"]).resolve(strict=True) if source.name != args.route or digest(source / "dimension-fixture.json") != record["baseFixtureSha256"]: raise AssertionError("Respawn fixture identity or definition differs from prior receipt") - target = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + target = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) args.fixtures, args.routes, args.target_manifest = source.parent, [source.name], args.profile - return run(args, target=target, stage=native119.stage, server_type=native119.Server, - check_log=native119.require_native_boot, approved_sources={source.name: record["fingerprint"]}) + return run(args, target=target, stage=native1201.stage, server_type=native1201.Server, + check_log=native1201.require_native_boot, approved_sources={source.name: record["fingerprint"]}) if __name__ == "__main__": diff --git a/test-rig/migration/native119_saved.py b/test-rig/migration/native1201_saved.py similarity index 94% rename from test-rig/migration/native119_saved.py rename to test-rig/migration/native1201_saved.py index ef30312e..9476d528 100644 --- a/test-rig/migration/native119_saved.py +++ b/test-rig/migration/native1201_saved.py @@ -1,4 +1,4 @@ -"""Verify the actual flattened terrain and block entity data written by 1.19.4.""" +"""Verify the actual flattened terrain and block entity data written by 1.20.1.""" import gzip import io @@ -13,7 +13,7 @@ from transformer_order import read_region -DATA_VERSION = 3337 +DATA_VERSION = 3465 def decode_chunk(payload, coordinates): @@ -24,7 +24,7 @@ def decode_chunk(payload, coordinates): raise ValueError("Unknown chunk compression") chunk = plain(nbtlib.File.parse(io.BytesIO(decoders[payload[4]](payload[5:]))).unpack()) if chunk.get("DataVersion") != DATA_VERSION or "Level" in chunk: - raise ValueError("Chunk was not written in native 1.19.4 format") + raise ValueError("Chunk was not written in native 1.20.1 format") if (chunk["xPos"], chunk["zPos"]) != coordinates: raise ValueError("Saved chunk coordinates do not match the region slot") sections = {} @@ -45,12 +45,12 @@ def decode_chunk(payload, coordinates): def capture(runtime, label, rows): world = runtime / WORLD - evidence = runtime / "native119-save" / label + evidence = runtime / "native1201-save" / label evidence.mkdir(parents=True) shutil.copy2(world / "level.dat", evidence / "level.dat") level = nbtlib.load(evidence / "level.dat")["Data"] if level["DataVersion"] != DATA_VERSION: - raise AssertionError("Saved level does not identify 1.19.4") + raise AssertionError("Saved level does not identify 1.20.1") regions, chunks = {}, {} for row in rows: x, y, z = pos = tuple(int(row[field]) for field in ("x", "y", "z")) diff --git a/test-rig/migration/native119_wolf_control.py b/test-rig/migration/native1201_wolf_control.py similarity index 86% rename from test-rig/migration/native119_wolf_control.py rename to test-rig/migration/native1201_wolf_control.py index 51306a2e..1150fb62 100644 --- a/test-rig/migration/native119_wolf_control.py +++ b/test-rig/migration/native1201_wolf_control.py @@ -7,7 +7,7 @@ import nbtlib from matrix import WORLD, digest, plain, write_json from native117 import output_path, require_disjoint -import native119 +import native1201 CASES = (("tame8", 8, True, 20), ("tame20", 20, True, 20), ("wild8", 8, False, 8)) @@ -42,15 +42,15 @@ def main(): output = output_path(args.output) for path in (args.profile, args.seed, args.inventory): require_disjoint(output, path) - seed, inventory, _ = native119.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) + seed, inventory, _ = native1201.read_target(args.profile, args.seed, args.inventory, args.inventory_sha256) with socket.socket() as port: port.bind(("127.0.0.1", args.port)) - launcher = native119.stage(output, (seed, inventory, {}), args.port, normal=True) - report = dict(status="RUNNING", scope="FRESH_FORGE_45_NO_MOD_JARS", nativeDataVersion=3337, + launcher = native1201.stage(output, (seed, inventory, {}), args.port, normal=True) + report = dict(status="RUNNING", scope="FRESH_FORGE_47_NO_MOD_JARS", nativeDataVersion=3465, inventorySha256=digest(args.inventory), boots={}) try: for phase in ("summon", "restarted"): - server = native119.Server(output, args.java17, launcher, phase) + server = native1201.Server(output, args.java17, launcher, phase) try: server.send("forceload add 0 0") server.send("say WOLF-CONTROL-CHUNK-TICKET") @@ -73,15 +73,15 @@ def main(): finally: server.close() report["boots"][phase] = observed - if int(nbtlib.load(output / WORLD / "level.dat")["Data"]["DataVersion"]) != 3337: - raise AssertionError("The control world is not native 1.19.4") + if int(nbtlib.load(output / WORLD / "level.dat")["Data"]["DataVersion"]) != 3465: + raise AssertionError("The control world is not native 1.20.1") report["status"] = "PASS" except BaseException as error: report.update(status="FAIL", error=repr(error)) raise finally: - write_json(output / "native119-wolf-control.json", report) - print("PASS: Forge 45 without any mods reproduced the native tame-wolf heal") + write_json(output / "native1201-wolf-control.json", report) + print("PASS: Forge 47 without any mods reproduced the native tame-wolf heal") if __name__ == "__main__": diff --git a/test-rig/migration/test_native119_log_policy.py b/test-rig/migration/test_native119_log_policy.py deleted file mode 100644 index c36a6102..00000000 --- a/test-rig/migration/test_native119_log_policy.py +++ /dev/null @@ -1,44 +0,0 @@ -from pathlib import Path -import tempfile -import tomllib -import unittest - -from native119 import log_findings, prepare_fml_defaults - - -PROBE = "jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable" -DEBUG = "[09Nov2026 15:22:51.470] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: " -DETAIL = ("java.lang.IllegalAccessException: class io.netty.util.internal.PlatformDependent0$7 " - "(in module io.netty.common) cannot access class jdk.internal.misc.Unsafe (in module java.base)") -FRAME = "\tat io.netty.util.internal.PlatformDependent0$7.run(PlatformDependent0.java:410)" - - -class Native119LogPolicyTests(unittest.TestCase): - def test_records_exact_netty_debug_fallback(self): - errors, diagnostics = log_findings("\n".join((DEBUG + PROBE, DETAIL, FRAME))) - self.assertEqual([], errors) - self.assertEqual([dict(probe=PROBE, detail=DETAIL)], diagnostics) - - def test_does_not_discard_same_exception_at_wrong_level_or_after_a_different_probe(self): - for header in (DEBUG.replace("/DEBUG]", "/ERROR]") + PROBE, DEBUG + "unrelated probe", ""): - errors, diagnostics = log_findings(header + "\n" + DETAIL) - self.assertIn(DETAIL, errors) - self.assertEqual([], diagnostics) - - def test_preserves_machine_failure_after_netty_probe(self): - error = "[15:22:53] [Server thread/ERROR] [minecraft/MinecraftServer]: Failed machine tick" - errors, _ = log_findings("\n".join((DEBUG + PROBE, DETAIL, FRAME, error))) - self.assertEqual([error], errors) - - def test_disposable_first_start_uses_forge_defaults_but_preserves_existing_config(self): - with tempfile.TemporaryDirectory() as directory: - runtime = Path(directory) - prepare_fml_defaults(runtime) - config = runtime / "config/fml.toml" - self.assertEqual({"versionCheck": True, "splashscreen": True, "disableOptimizedDFU": True, - "defaultConfigPath": "defaultconfigs", "maxThreads": -1}, - tomllib.loads(config.read_text(encoding="utf-8"))) - original = b'maxThreads = 2\n' - config.write_bytes(original) - prepare_fml_defaults(runtime) - self.assertEqual(original, config.read_bytes()) diff --git a/test-rig/migration/test_native1201_log_policy.py b/test-rig/migration/test_native1201_log_policy.py new file mode 100644 index 00000000..6c4a4c40 --- /dev/null +++ b/test-rig/migration/test_native1201_log_policy.py @@ -0,0 +1,66 @@ +from pathlib import Path +import tempfile +import tomllib +import unittest + +from native1201 import log_findings, prepare_fml_defaults + + +PROBE = "jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable" +DEBUG = "[09Nov2026 15:22:51.470] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: " +DETAIL = ("java.lang.IllegalAccessException: class io.netty.util.internal.PlatformDependent0$7 " + "(in module io.netty.common) cannot access class jdk.internal.misc.Unsafe (in module java.base)") +FRAME = "\tat io.netty.util.internal.PlatformDependent0$7.run(PlatformDependent0.java:410)" + + +class Native1201LogPolicyTests(unittest.TestCase): + def test_records_exact_netty_debug_fallback(self): + errors, diagnostics = log_findings("\n".join((DEBUG + PROBE, DETAIL, FRAME))) + self.assertEqual([], errors) + self.assertEqual([dict(probe=PROBE, detail=DETAIL)], diagnostics) + + def test_does_not_discard_same_exception_at_wrong_level_or_after_a_different_probe(self): + for header in (DEBUG.replace("/DEBUG]", "/ERROR]") + PROBE, DEBUG + "unrelated probe", ""): + errors, diagnostics = log_findings(header + "\n" + DETAIL) + self.assertIn(DETAIL, errors) + self.assertEqual([], diagnostics) + + def test_preserves_machine_failure_after_netty_probe(self): + error = "[15:22:53] [Server thread/ERROR] [minecraft/MinecraftServer]: Failed machine tick" + errors, _ = log_findings("\n".join((DEBUG + PROBE, DETAIL, FRAME, error))) + self.assertEqual([error], errors) + + def test_disposable_first_start_uses_forge_defaults_except_the_external_check(self): + with tempfile.TemporaryDirectory() as directory: + runtime = Path(directory) + prepare_fml_defaults(runtime) + config = runtime / "config/fml.toml" + self.assertEqual({"versionCheck": False, "disableOptimizedDFU": True, + "defaultConfigPath": "defaultconfigs", "maxThreads": -1, + "earlyWindowHeight": 480, "earlyWindowWidth": 854, + "earlyWindowControl": True, "earlyWindowFBScale": 1, + "earlyWindowProvider": "fmlearlywindow", "earlyWindowMaximized": False, + "earlyWindowSkipGLVersions": [], "earlyWindowLogHelpMessage": True, + "earlyWindowSquir": False, "earlyWindowShowCPU": False}, + tomllib.loads(config.read_text(encoding="utf-8"))) + def test_copied_forge_configuration_changes_only_the_external_check(self): + for original in (b'maxThreads = 2\n', b'versionCheck = true # preserve comment\r\nmaxThreads = 2\r\n'): + with self.subTest(original=original), tempfile.TemporaryDirectory() as directory: + runtime = Path(directory) + config = runtime / "config/fml.toml" + config.parent.mkdir() + config.write_bytes(original) + prepare_fml_defaults(runtime) + self.assertEqual({"versionCheck": False, "maxThreads": 2}, + tomllib.loads(config.read_text(encoding="utf-8"))) + self.assertEqual(original, (runtime / "fml-pre-qualification.toml").read_bytes()) + disabled = config.read_bytes() + if b"#" in original: + self.assertEqual(original.replace(b"true", b"false"), disabled) + prepare_fml_defaults(runtime) + self.assertEqual(disabled, config.read_bytes()) + + def test_update_check_errors_still_fail_if_they_appear(self): + error = "com.google.gson.JsonSyntaxException: Expected BEGIN_OBJECT but was NUMBER" + errors, _ = log_findings("[Forge Version Check/WARN] Failed to process update information\n" + error) + self.assertEqual([error], errors) diff --git a/test-rig/profiles/native1201/dev-core-apocalyptic.json b/test-rig/profiles/native1201/dev-core-apocalyptic.json new file mode 100644 index 00000000..5171a2ab --- /dev/null +++ b/test-rig/profiles/native1201/dev-core-apocalyptic.json @@ -0,0 +1,44 @@ +{ + "name": "dev-core-apocalyptic", + "mode": "development", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011-deobf.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs-dev/baseSteam-2.2.13.120011-deobf.jar", + "sha256": "55EBFDCEBA4A86A3E7AD0B60AA7F6855C30B33FF5148D2BE8C6750F9400D4B99" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011-deobf.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs-dev/baseElectric-2.2.13.120011-deobf.jar", + "sha256": "14107B4602E4749FD1FD570F7974B420AB425CB05CE82C0A080D9A3A2747E3C5" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011-deobf.jar", + "path": "build/gradle/libs-dev/AdvantageWorksTestHarness-1.1.4.120011-deobf.jar", + "sha256": "99514AE1CB24232218690F381B643ED471972C8F6F46513A19B57D3A1B16BE7D" + } + ], + "recipeMode": "APOCALYPTIC" +} diff --git a/test-rig/profiles/native1201/dev-core-tech-progression.json b/test-rig/profiles/native1201/dev-core-tech-progression.json new file mode 100644 index 00000000..6d7e1ae3 --- /dev/null +++ b/test-rig/profiles/native1201/dev-core-tech-progression.json @@ -0,0 +1,44 @@ +{ + "name": "dev-core-tech-progression", + "mode": "development", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011-deobf.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs-dev/baseSteam-2.2.13.120011-deobf.jar", + "sha256": "55EBFDCEBA4A86A3E7AD0B60AA7F6855C30B33FF5148D2BE8C6750F9400D4B99" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011-deobf.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs-dev/baseElectric-2.2.13.120011-deobf.jar", + "sha256": "14107B4602E4749FD1FD570F7974B420AB425CB05CE82C0A080D9A3A2747E3C5" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011-deobf.jar", + "path": "build/gradle/libs-dev/AdvantageWorksTestHarness-1.1.4.120011-deobf.jar", + "sha256": "99514AE1CB24232218690F381B643ED471972C8F6F46513A19B57D3A1B16BE7D" + } + ], + "recipeMode": "TECH_PROGRESSION" +} diff --git a/test-rig/profiles/native1201/dev-core.json b/test-rig/profiles/native1201/dev-core.json new file mode 100644 index 00000000..0bb46fb1 --- /dev/null +++ b/test-rig/profiles/native1201/dev-core.json @@ -0,0 +1,43 @@ +{ + "name": "dev-core", + "mode": "development", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011-deobf.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs-dev/baseSteam-2.2.13.120011-deobf.jar", + "sha256": "55EBFDCEBA4A86A3E7AD0B60AA7F6855C30B33FF5148D2BE8C6750F9400D4B99" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011-deobf.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs-dev/baseElectric-2.2.13.120011-deobf.jar", + "sha256": "14107B4602E4749FD1FD570F7974B420AB425CB05CE82C0A080D9A3A2747E3C5" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011-deobf.jar", + "path": "build/gradle/libs-dev/AdvantageWorksTestHarness-1.1.4.120011-deobf.jar", + "sha256": "99514AE1CB24232218690F381B643ED471972C8F6F46513A19B57D3A1B16BE7D" + } + ] +} diff --git a/test-rig/profiles/native1201/packaged-current.json b/test-rig/profiles/native1201/packaged-current.json new file mode 100644 index 00000000..801ec0cd --- /dev/null +++ b/test-rig/profiles/native1201/packaged-current.json @@ -0,0 +1,64 @@ +{ + "name": "packaged-current", + "mode": "packaged", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "basemetals", + "version": "3.1.2.120011", + "file": "BaseMetals-3.1.2.120011.jar", + "path": "../../../../BaseMetals/BaseMetals 1201/BaseMetals/build/libs/BaseMetals-3.1.2.120011.jar", + "sha256": "30FC6777300E0E48FBB63E3250E86122DAFA38CCA5AD5878CB795C72B7CCCCDE" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + } + ] +} diff --git a/test-rig/profiles/native1201/packaged-decoupled.json b/test-rig/profiles/native1201/packaged-decoupled.json new file mode 100644 index 00000000..d9a3194d --- /dev/null +++ b/test-rig/profiles/native1201/packaged-decoupled.json @@ -0,0 +1,57 @@ +{ + "name": "packaged-decoupled", + "mode": "packaged", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + } + ] +} diff --git a/test-rig/profiles/native1201/packaged-mineralogy.json b/test-rig/profiles/native1201/packaged-mineralogy.json new file mode 100644 index 00000000..4ce40ce9 --- /dev/null +++ b/test-rig/profiles/native1201/packaged-mineralogy.json @@ -0,0 +1,68 @@ +{ + "name": "packaged-mineralogy", + "mode": "packaged", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + }, + { + "id": "mineralogy", + "version": "6.1.4.120011", + "file": "Mineralogy-6.1.4.120011.jar", + "path": "../../../../BaseMetals/.verification-basemetals1201/dependencies/Mineralogy-6.1.4.120011.jar", + "sha256": "1172C7FF424BCE10E3EAC7A790353CAB35E5A5F06EBB019B31BED05B90ED8A5F" + } + ], + "lifecycleStations": [ + "W-03", + "S-01" + ] +} diff --git a/test-rig/profiles/native1201/packaged-optional-power.json b/test-rig/profiles/native1201/packaged-optional-power.json new file mode 100644 index 00000000..e4770e81 --- /dev/null +++ b/test-rig/profiles/native1201/packaged-optional-power.json @@ -0,0 +1,60 @@ +{ + "name": "packaged-optional-power", + "mode": "packaged", + "runtimeBase": "build/works-native1201", + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01", + "levelType": "minecraft:flat", + "levelSeed": "advantage-works-1.20.1-v1", + "startupTimeoutSeconds": 180, + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + } + ], + "lifecycleStations": [ + "P-API-01" + ] +} diff --git a/test-rig/profiles/native1201/worldgen-advantage.json b/test-rig/profiles/native1201/worldgen-advantage.json new file mode 100644 index 00000000..e0b18bbb --- /dev/null +++ b/test-rig/profiles/native1201/worldgen-advantage.json @@ -0,0 +1,153 @@ +{ + "mode": "packaged", + "runtimeBase": "build/works-native1201-worldgen", + "serverPort": 25565, + "startupTimeoutSeconds": 180, + "stationRunSeconds": 5, + "recipeMode": "NORMAL", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + } + ], + "name": "worldgen-advantage", + "levelName": "AdvantageWorksWorldgen", + "levelSeed": "advantage-works-worldgen-1.15.2-v1", + "levelType": "minecraft:normal", + "generatorSettings": "", + "buildWorks": false, + "worldgenSampleRadius": 8, + "shutdownTimeoutSeconds": 300, + "lifecycleStations": [], + "firstProfileAssertions": [ + { + "id": "desert-oil-visible", + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "desert-oil-owner", + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "present": true, + "field": "source_provider", + "expectedString": "basepower" + }, + { + "id": "electric-sulfur-default", + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "electric-lithium-default", + "section": "ores", + "entry": "baseelectric:ore/lithium", + "present": true, + "field": "enabled", + "expectedBoolean": true + } + ], + "profileMutations": [ + { + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "field": "enabled", + "booleanValue": false + }, + { + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "field": "enabled", + "booleanValue": false + } + ], + "restartProfileAssertions": [ + { + "id": "desert-oil-user-disable-persists", + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "present": true, + "field": "enabled", + "expectedBoolean": false + }, + { + "id": "electric-sulfur-user-disable-persists", + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "present": true, + "field": "enabled", + "expectedBoolean": false + }, + { + "id": "electric-lithium-remains-enabled", + "section": "ores", + "entry": "baseelectric:ore/lithium", + "present": true, + "field": "enabled", + "expectedBoolean": true + } + ], + "worldgenExpectations": { + "minimumCounts": { + "basepower:crude_oil": 1, + "baseelectric:li_ore": 1, + "baseelectric:sulfur_ore": 1 + }, + "maximumCounts": { + "mineralogy:crude_oil": 0, + "mineralogy:sulfur_ore": 0 + }, + "zeroBiomeViolations": true + }, + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "inputStatus": "ARTIFACTS_AND_SOURCES_PINNED_QUALIFICATION_PENDING", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01" +} diff --git a/test-rig/profiles/native1201/worldgen-legacy-import.json b/test-rig/profiles/native1201/worldgen-legacy-import.json new file mode 100644 index 00000000..001565e8 --- /dev/null +++ b/test-rig/profiles/native1201/worldgen-legacy-import.json @@ -0,0 +1,220 @@ +{ + "mode": "packaged", + "runtimeBase": "build/works-native1201-worldgen", + "serverPort": 25565, + "startupTimeoutSeconds": 180, + "stationRunSeconds": 5, + "recipeMode": "NORMAL", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + } + ], + "name": "worldgen-legacy-import", + "levelName": "AdvantageWorksWorldgen", + "levelSeed": "advantage-works-worldgen-1.15.2-v1", + "levelType": "minecraft:normal", + "generatorSettings": "", + "buildWorks": false, + "worldgenSampleRadius": 8, + "stableWorldgenCountExclusions": [ + "basepower:crude_oil" + ], + "shutdownTimeoutSeconds": 300, + "lifecycleStations": [], + "configFixtures": [ + { + "source": "../../../PA113/PowerAdvantage/test-rig/../src/test/resources/orespawn-legacy/poweradvantage.json", + "destination": "config/orespawn/poweradvantage.json" + }, + { + "source": "../../../PA113/PowerAdvantage/test-rig/../../ElectricAdvantage/ElectricAdvantage/src/test/resources/orespawn-legacy/electricadvantage.json", + "destination": "config/orespawn/electricadvantage.json" + } + ], + "firstProfileAssertions": [ + { + "id": "legacy-oil-retained", + "section": "ores", + "entry": "basepower:legacy/basepower_crude_oil_0", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "legacy-lithium-retained", + "section": "ores", + "entry": "baseelectric:legacy/baseelectric_li_ore_0", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "legacy-sulfur-retained", + "section": "ores", + "entry": "baseelectric:legacy/baseelectric_sulfur_ore_1", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "modern-oil-not-duplicated", + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "present": false + }, + { + "id": "modern-lithium-not-duplicated", + "section": "ores", + "entry": "baseelectric:ore/lithium", + "present": false + }, + { + "id": "modern-sulfur-not-duplicated", + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "present": false + } + ], + "restartProfileAssertions": [ + { + "id": "legacy-oil-retained", + "section": "ores", + "entry": "basepower:legacy/basepower_crude_oil_0", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "legacy-lithium-retained", + "section": "ores", + "entry": "baseelectric:legacy/baseelectric_li_ore_0", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "legacy-sulfur-retained", + "section": "ores", + "entry": "baseelectric:legacy/baseelectric_sulfur_ore_1", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "modern-oil-not-duplicated", + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "present": false + }, + { + "id": "modern-lithium-not-duplicated", + "section": "ores", + "entry": "baseelectric:ore/lithium", + "present": false + }, + { + "id": "modern-sulfur-not-duplicated", + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "present": false + } + ], + "firstFileAssertions": [ + { + "id": "migration-report", + "path": "config/orespawn-os3-migration-report.json", + "contains": "os1_config_source", + "minimumOccurrences": 2 + }, + { + "id": "power-provider", + "path": "config/basepower-orespawn.json", + "contains": "basepower:legacy/basepower_crude_oil_0", + "minimumOccurrences": 1 + }, + { + "id": "electric-provider", + "path": "config/baseelectric-orespawn.json", + "contains": "baseelectric:legacy/baseelectric_li_ore_0", + "minimumOccurrences": 1 + } + ], + "restartFileAssertions": [ + { + "id": "migration-report", + "path": "config/orespawn-os3-migration-report.json", + "contains": "os1_config_source", + "minimumOccurrences": 2 + }, + { + "id": "power-provider", + "path": "config/basepower-orespawn.json", + "contains": "basepower:legacy/basepower_crude_oil_0", + "minimumOccurrences": 1 + }, + { + "id": "electric-provider", + "path": "config/baseelectric-orespawn.json", + "contains": "baseelectric:legacy/baseelectric_li_ore_0", + "minimumOccurrences": 1 + } + ], + "worldgenExpectations": { + "minimumCounts": { + "basepower:crude_oil": 1, + "baseelectric:li_ore": 1, + "baseelectric:sulfur_ore": 1 + }, + "maximumCounts": { + "mineralogy:crude_oil": 0, + "mineralogy:sulfur_ore": 0 + }, + "zeroBiomeViolations": false + }, + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "inputStatus": "ARTIFACTS_AND_SOURCES_PINNED_QUALIFICATION_PENDING", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01" +} diff --git a/test-rig/profiles/native1201/worldgen-mineralogy.json b/test-rig/profiles/native1201/worldgen-mineralogy.json new file mode 100644 index 00000000..23cbf19f --- /dev/null +++ b/test-rig/profiles/native1201/worldgen-mineralogy.json @@ -0,0 +1,162 @@ +{ + "mode": "packaged", + "runtimeBase": "build/works-native1201-worldgen", + "serverPort": 25565, + "startupTimeoutSeconds": 180, + "stationRunSeconds": 5, + "recipeMode": "NORMAL", + "sourceCommit": "83a3f028ffad220fe2f3cc4983a9340dde2295a8", + "sourceVersion": "2.4.12.120011", + "forge": { + "version": "1.20.1-47.4.10", + "installerPath": "../../../../BaseMetals/.verification-basemetals1201/dependencies/forge-1.20.1-47.4.10-installer.jar", + "url": "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar", + "sha256": "1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3" + }, + "mods": [ + { + "id": "basepower", + "version": "2.4.12.120011", + "file": "basePower-2.4.12.120011.jar", + "path": "../build/libs/basePower-2.4.12.120011.jar", + "sha256": "E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A" + }, + { + "id": "basesteam", + "version": "2.2.13.120011", + "file": "baseSteam-2.2.13.120011.jar", + "path": "../../SteamAdvantage/SteamAdvantage/build/libs/baseSteam-2.2.13.120011.jar", + "sha256": "248F87F7731472025C73F766F7B634268AC38CC987C4CA41E4743C229D54B80E" + }, + { + "id": "baseelectric", + "version": "2.2.13.120011", + "file": "baseElectric-2.2.13.120011.jar", + "path": "../../ElectricAdvantage/ElectricAdvantage/build/libs/baseElectric-2.2.13.120011.jar", + "sha256": "9344CFCE7B9FB725957F885E2A21FC207DCD58679ED95D319DA04CE854576C5F" + }, + { + "id": "orespawn", + "version": "4.1.0.120011", + "file": "OreSpawn-4.1.0.120011.jar", + "path": "../../../../MinecraftMineralogy/OS1201/OreSpawn/build/libs/OreSpawn-4.1.0.120011.jar", + "sha256": "E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0" + }, + { + "id": "advantageworkstest", + "version": "1.1.4.120011", + "file": "AdvantageWorksTestHarness-1.1.4.120011.jar", + "path": "build/gradle/libs/AdvantageWorksTestHarness-1.1.4.120011.jar", + "sha256": "26654C0A363818FD088DF80900D63E8E4B0981A8A4AE6BEDAC7758853095861D" + }, + { + "id": "mineralogy", + "version": "6.1.4.120011", + "file": "Mineralogy-6.1.4.120011.jar", + "path": "../../../../BaseMetals/.verification-basemetals1201/dependencies/Mineralogy-6.1.4.120011.jar", + "sha256": "1172C7FF424BCE10E3EAC7A790353CAB35E5A5F06EBB019B31BED05B90ED8A5F" + } + ], + "name": "worldgen-mineralogy", + "levelName": "AdvantageWorksWorldgen", + "levelSeed": "advantage-works-worldgen-1.15.2-v1", + "levelType": "minecraft:normal", + "generatorSettings": "", + "buildWorks": false, + "worldgenSampleRadius": 16, + "shutdownTimeoutSeconds": 300, + "lifecycleStations": [], + "firstProfileAssertions": [ + { + "id": "desert-oil-enabled", + "section": "fluid_deposits", + "entry": "basepower:fluid_deposit/desert_crude_oil", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "ocean-oil-enabled", + "section": "fluid_deposits", + "entry": "mineralogy:fluid_deposit/crude_oil", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "mineralogy-sulfur-enabled", + "section": "ores", + "entry": "mineralogy:ore/mineralogy/sulfur_ore", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "electric-sulfur-disabled", + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "present": true, + "field": "enabled", + "expectedBoolean": false + }, + { + "id": "electric-lithium-fallback-enabled", + "section": "ores", + "entry": "baseelectric:ore/lithium", + "present": true, + "field": "enabled", + "expectedBoolean": true + } + ], + "profileMutations": [ + { + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "field": "enabled", + "booleanValue": true + } + ], + "restartProfileAssertions": [ + { + "id": "electric-sulfur-user-enable-persists", + "section": "ores", + "entry": "baseelectric:ore/sulfur", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "mineralogy-sulfur-remains-enabled", + "section": "ores", + "entry": "mineralogy:ore/mineralogy/sulfur_ore", + "present": true, + "field": "enabled", + "expectedBoolean": true + }, + { + "id": "ocean-oil-remains-enabled", + "section": "fluid_deposits", + "entry": "mineralogy:fluid_deposit/crude_oil", + "present": true, + "field": "enabled", + "expectedBoolean": true + } + ], + "worldgenExpectations": { + "minimumCounts": { + "mineralogy:crude_oil": 1, + "mineralogy:sulfur_ore": 1, + "basepower:crude_oil": 1, + "baseelectric:li_ore": 1 + }, + "maximumCounts": { + "baseelectric:sulfur_ore": 0 + }, + "zeroBiomeViolations": true + }, + "minecraftVersion": "1.20.1", + "portStatus": "PORTED_UNQUALIFIED", + "qualificationStatus": "UNQUALIFIED", + "inputStatus": "ARTIFACTS_AND_SOURCES_PINNED_QUALIFICATION_PENDING", + "powerDeobfSha256": "21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01" +} diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksCommand.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksCommand.java index 8f6c1958..c0e10805 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksCommand.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksCommand.java @@ -61,7 +61,7 @@ private static int execute(CommandSourceStack source, String operation, String t case "checkpoint": message = controller.checkpoint(source.getServer(), target, name); break; default: throw new IllegalArgumentException("Unknown Advantage Works operation " + operation); } - source.sendSuccess(Component.literal(message), false); + source.sendSuccess(() -> Component.literal(message), false); return 1; } catch (RuntimeException ex) { LOGGER.error("Advantage Works command failed: {} {}", operation, target, ex); @@ -72,7 +72,8 @@ private static int execute(CommandSourceStack source, String operation, String t private static int sampleWorldgen(CommandSourceStack source, int radius) { WorksController controller = WorksController.getInstance(); controller.requireAuthorizedWorld(source.getServer()); - source.sendSuccess(Component.literal(controller.sampleWorldgen(source.getServer(), radius)), false); + String sample = controller.sampleWorldgen(source.getServer(), radius); + source.sendSuccess(() -> Component.literal(sample), false); return 1; } } diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksMod.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksMod.java index b148ff6f..5c5569a5 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksMod.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/AdvantageWorksMod.java @@ -7,7 +7,7 @@ @Mod(AdvantageWorksMod.MODID) public final class AdvantageWorksMod { public static final String MODID = "advantageworkstest"; - public static final String VERSION = "1.1.3.119041"; + public static final String VERSION = "1.1.4.120011"; public AdvantageWorksMod() { MigrationProbe.register(); diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/DimensionEntityProbe.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/DimensionEntityProbe.java index 8731e41a..da0cee64 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/DimensionEntityProbe.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/DimensionEntityProbe.java @@ -296,7 +296,7 @@ private static ServerPlayer readPlayer(MinecraftServer server, ServerLevel world ServerPlayer player = new ServerPlayer(server, world, new GameProfile(UUID.fromString(definition.get("playerUuid").getAsString()), definition.get("playerName").getAsString())); if (server.getPlayerList().load(player) == null) throw new IllegalStateException("No player file loaded"); - if (Native117Worlds.legacyId(player.getLevel().dimension()) != dimension(definition) || player.getLevel() != world) { + if (Native117Worlds.legacyId(player.level().dimension()) != dimension(definition) || player.level() != world) { throw new IllegalStateException("Player loaded in wrong dimension"); } return player; @@ -313,7 +313,7 @@ private JsonObject snapshot(MinecraftServer server, ServerLevel world, JsonObjec result.addProperty("playerAdapter", read); result.add("playerWorldDimension", JsonNull.INSTANCE); if (read) { ServerPlayer player = readPlayer(server, world, definition); - result.addProperty("playerWorldDimension", Native117Worlds.legacyId(player.getLevel().dimension())); + result.addProperty("playerWorldDimension", Native117Worlds.legacyId(player.level().dimension())); result.add("player", encode(player.saveWithoutId(new CompoundTag()))); if (operation.equals("respawn")) result.add("respawn", respawn(server, world, definition, player)); else Native117PlayerIo.save(server.getPlayerList(), player); @@ -376,7 +376,7 @@ private static JsonObject respawn(MinecraftServer server, ServerLevel world, Jso result.addProperty("handler", "ServerPlayNetHandler.PERFORM_RESPAWN"); result.addProperty("keepInventory", keep); result.addProperty("bedMode", bedMode); CompoundTag before = player.saveWithoutId(new CompoundTag()); - result.addProperty("fromDimension", Native117Worlds.legacyId(player.getLevel().dimension())); result.add("before", encode(before)); + result.addProperty("fromDimension", Native117Worlds.legacyId(player.level().dimension())); result.add("before", encode(before)); JsonObject diagnostics = new JsonObject(); result.add("spawnDiagnostics", diagnostics); diagnostics.add("before", spawnDiagnostics(player, before)); Set existing = Collections.newSetFromMap(new IdentityHashMap()); Native117Worlds.entities(world).forEach(existing::add); @@ -399,7 +399,7 @@ private static JsonObject respawn(MinecraftServer server, ServerLevel world, Jso CompoundTag after = replacement.saveWithoutId(new CompoundTag()); result.add("after", encode(after)); diagnostics.add("after", spawnDiagnostics(replacement, after)); - result.addProperty("toDimension", Native117Worlds.legacyId(replacement.getLevel().dimension())); + result.addProperty("toDimension", Native117Worlds.legacyId(replacement.level().dimension())); BlockPos bed = replacement.getRespawnPosition(); result.add("bedLocation", bed == null ? JsonNull.INSTANCE : JSON.toJsonTree(new int[] {bed.getX(), bed.getY(), bed.getZ()})); JsonArray drops = new JsonArray(); @@ -421,7 +421,7 @@ private static JsonObject respawn(MinecraftServer server, ServerLevel world, Jso private static JsonObject spawnDiagnostics(ServerPlayer player, CompoundTag nbt) { JsonObject result = new JsonObject(); result.addProperty("queryDimension", 0); - result.addProperty("playerWorldDimension", Native117Worlds.legacyId(player.getLevel().dimension())); + result.addProperty("playerWorldDimension", Native117Worlds.legacyId(player.level().dimension())); result.addProperty("spawnDimension", Native117Worlds.legacyId(player.getRespawnDimension())); BlockPos bed = player.getRespawnPosition(); result.add("bedLocation", bed == null ? JsonNull.INSTANCE : JSON.toJsonTree(new int[] {bed.getX(), bed.getY(), bed.getZ()})); diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117EntityContext.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117EntityContext.java index 1dc6ef7d..88dd2816 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117EntityContext.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117EntityContext.java @@ -16,18 +16,18 @@ static JsonObject observe(Entity entity, ServerLevel world) { Set seen = Collections.newSetFromMap(new IdentityHashMap()); collect(entity, world, worlds, seen); JsonObject result = new JsonObject(); - result.addProperty("worldDimensionKey", entity.level.dimension().location().toString()); + result.addProperty("worldDimensionKey", entity.level().dimension().location().toString()); result.addProperty("sameWorld", true); result.add("entityWorlds", worlds); return result; } private static void collect(Entity entity, ServerLevel world, JsonObject worlds, Set seen) { - if (entity.level != world) throw new IllegalStateException("Dimension witness belongs to another world instance"); + if (entity.level() != world) throw new IllegalStateException("Dimension witness belongs to another world instance"); if (!seen.add(entity)) throw new IllegalStateException("Repeated entity in dimension observation"); String uuid = entity.getUUID().toString(); if (worlds.has(uuid)) throw new IllegalStateException("Duplicate UUID in dimension observation"); - worlds.addProperty(uuid, entity.level.dimension().location().toString()); + worlds.addProperty(uuid, entity.level().dimension().location().toString()); for (Entity passenger : entity.getPassengers()) collect(passenger, world, worlds, seen); } } diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117Readiness.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117Readiness.java index 189115f7..efb5b30f 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117Readiness.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117Readiness.java @@ -82,7 +82,7 @@ private void tick(TickEvent.LevelTickEvent event) { if (!observation.observe(world.getGameTime(), System.nanoTime(), states)) return; JsonObject report = observation.report(); report.addProperty("label", label); - report.addProperty("minecraft", "1.19.4"); + report.addProperty("minecraft", "1.20.1"); report.addProperty("dimension", world.dimension().location().toString()); try { Files.createDirectories(output.toPath().getParent()); diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117StoppedEntitiesSnapshot.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117StoppedEntitiesSnapshot.java index 0fdb3e02..003584e5 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117StoppedEntitiesSnapshot.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/Native117StoppedEntitiesSnapshot.java @@ -130,7 +130,7 @@ static JsonArray entities(ServerLevel world, Iterable available, Set available, Set held = new IdentityHashMap<>(); void hold(Entity entity) { - if (!(entity.level instanceof ServerLevel)) throw new AssertionError("Entity hold requires a native server world"); + if (!(entity.level() instanceof ServerLevel)) throw new AssertionError("Entity hold requires a native server world"); if (!held.containsKey(entity)) { State state = new State(entity); held.put(entity, state); @@ -35,7 +35,7 @@ private static final class State { State(Entity entity) { ticks = entity.tickCount; - gate = NativeEntityTickGate.of((ServerLevel) entity.level); + gate = NativeEntityTickGate.of((ServerLevel) entity.level()); } } } diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeHarvestProbe.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeHarvestProbe.java index e627ad03..562632da 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeHarvestProbe.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeHarvestProbe.java @@ -218,7 +218,7 @@ private static void run(ServerLevel world, String label) throws Exception { harvestDrops(world, new AABB(POS).inflate(2)).forEach(ItemEntity::discard); JsonObject report = new JsonObject(); report.addProperty("label", label); - report.addProperty("minecraft", "1.19.4"); + report.addProperty("minecraft", "1.20.1"); report.addProperty("worldTime", world.getGameTime()); report.addProperty("fixtureIsolation", "native117-live-drops-v1"); report.addProperty("status", java.util.stream.StreamSupport.stream(rows.spliterator(), false) diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeTicketGeometry.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeTicketGeometry.java index 7db7cf26..58bb7d5b 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeTicketGeometry.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/NativeTicketGeometry.java @@ -7,8 +7,8 @@ import java.util.Set; import java.util.TreeSet; import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkLevel; +import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.Ticket; import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.TicketType; @@ -23,9 +23,9 @@ private NativeTicketGeometry() {} static Map observe(ServerLevel world) { try { int fullLevel = -1, entityTickingLevel = -1; - for (int level = 0; level <= ChunkMap.MAX_CHUNK_DISTANCE; level++) { - if (ChunkHolder.getStatus(level) == ChunkStatus.FULL) fullLevel = level; - if (ChunkHolder.getFullChunkStatus(level) == ChunkHolder.FullChunkStatus.ENTITY_TICKING) + for (int level = 0; level <= ChunkLevel.MAX_LEVEL; level++) { + if (ChunkLevel.generationStatus(level) == ChunkStatus.FULL) fullLevel = level; + if (ChunkLevel.fullStatus(level) == FullChunkStatus.ENTITY_TICKING) entityTickingLevel = level; } ServerChunkCache provider = world.getChunkSource(); @@ -45,12 +45,12 @@ static Map observe(ServerLevel world) { result.put("fullLevel", fullLevel); result.put("entityTickingLevel", entityTickingLevel); result.put("maxDistance", ChunkStatus.maxDistance()); - result.put("lastHolderLevel", ChunkMap.MAX_CHUNK_DISTANCE); - result.put("holderRadius", ChunkMap.MAX_CHUNK_DISTANCE - entityTickingLevel); + result.put("lastHolderLevel", ChunkLevel.MAX_LEVEL); + result.put("holderRadius", ChunkLevel.MAX_LEVEL - entityTickingLevel); result.put("observedForcedLevels", new ArrayList<>(forcedLevels)); return result; } catch (Exception error) { - throw new IllegalStateException("Cannot observe native Forge 36 ticket geometry", error); + throw new IllegalStateException("Cannot observe native chunk ticket geometry", error); } } } diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/ProgressionProbe.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/ProgressionProbe.java index a2cbc194..db463bd9 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/ProgressionProbe.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/ProgressionProbe.java @@ -27,6 +27,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.SimpleContainer; import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.inventory.TransientCraftingContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; @@ -42,6 +43,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.LootParams; import net.minecraftforge.common.MinecraftForge; import net.minecraft.world.item.crafting.RecipeType; import net.minecraftforge.event.RegisterCommandsEvent; @@ -99,22 +101,23 @@ private void audit(MinecraftServer server, ServerLevel world, String label) thro if (item != null) acquire(known, player, new ItemStack(item), "natural_resource", Collections.emptyList()); } JsonArray loot = new JsonArray(); - var overriddenTable = server.getLootTables().get(new ResourceLocation("minecraft:chests/simple_dungeon")); + var overriddenTable = server.getLootData().getLootTable(new ResourceLocation("minecraft:chests/simple_dungeon")); + LootParams chest = chestParams(world); for (int seed = 0; seed < 8; seed++) { List raw = new ArrayList<>(); - overriddenTable.getRandomItemsRaw(chestContext(world, seed), raw::add); + overriddenTable.getRandomItemsRaw(new LootContext.Builder(chest).withOptionalRandomSeed(seed + 1L).create(null), raw::add); require(raw.size() == 1 && id(raw.get(0)).equals("minecraft:dirt") && raw.get(0).getCount() == 1, "Player loot data-pack override was changed"); // Base Metals has its own Forge global modifier. It may add loot after the table runs. - List gameplay = overriddenTable.getRandomItems(chestContext(world, seed)); + List gameplay = overriddenTable.getRandomItems(chest, seed + 1L); require(gameplay.stream().filter(stack -> id(stack).equals("minecraft:dirt")).mapToInt(ItemStack::getCount).sum() == 1 && gameplay.stream().noneMatch(ProgressionProbe::advantage), "The live loot pipeline changed the override's contents or added Advantage parts"); } if (PowerAdvantage.recipeMode == RecipeMode.APOCALYPTIC) { for (int i = 0; i < 4096; i++) { - for (ItemStack stack : server.getLootTables().get( - new ResourceLocation("minecraft:chests/abandoned_mineshaft")).getRandomItems(chestContext(world, i))) { + for (ItemStack stack : server.getLootData().getLootTable( + new ResourceLocation("minecraft:chests/abandoned_mineshaft")).getRandomItems(chest, i + 1L)) { if (advantage(stack)) { if (acquire(known, player, stack, "vanilla_chest_loot", Collections.emptyList())) loot.add(id(stack)); } @@ -160,7 +163,7 @@ private void audit(MinecraftServer server, ServerLevel world, String label) thro }; for (int width = 1; width <= 3 && result.isEmpty(); width++) { if (ingredients.size() > width * 3) continue; - CraftingContainer grid = new CraftingContainer(container, 3, 3); + CraftingContainer grid = new TransientCraftingContainer(container, 3, 3); for (int i = 0; i < ingredients.size(); i++) grid.setItem((i / width) * 3 + i % width, ingredients.get(i)); result = matchedResult(recipe, grid, world); } @@ -264,8 +267,8 @@ static ItemStack stack(String id) { return item == null ? ItemStack.EMPTY : new ItemStack(item); } - private static LootContext chestContext(ServerLevel world, int seed) { - return new LootContext.Builder(world).withRandom(net.minecraft.util.RandomSource.create(seed)) + private static LootParams chestParams(ServerLevel world) { + return new LootParams.Builder(world) .withParameter(net.minecraft.world.level.storage.loot.parameters.LootContextParams.ORIGIN, new net.minecraft.world.phys.Vec3(0, 80, 0)) .create(net.minecraft.world.level.storage.loot.parameters.LootContextParamSets.CHEST); } diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/RecipeBookProbe.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/RecipeBookProbe.java index cf822174..fd6572ec 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/RecipeBookProbe.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/RecipeBookProbe.java @@ -85,7 +85,7 @@ static void verify(MinecraftServer server, ServerLevel world, String label, Json } private static CraftingContainer grid(int width) { - return new CraftingContainer(new AbstractContainerMenu(null, 0) { + return new net.minecraft.world.inventory.TransientCraftingContainer(new AbstractContainerMenu(null, 0) { @Override public boolean stillValid(net.minecraft.world.entity.player.Player player) { return true; } @Override public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int slot) { return ItemStack.EMPTY; diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksController.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksController.java index b21af06c..b8dfa63b 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksController.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksController.java @@ -82,7 +82,7 @@ static WorksController getInstance() { synchronized void loadDefinition() { if (definition != null) return; - definition = WorksDefinitionLoader.loadNative119(); + definition = WorksDefinitionLoader.loadNative1201(); for (WorksDefinition.Station station : definition.stations) { stations.put(station.id.toUpperCase(Locale.ROOT), station); statuses.put(station.id, "NOT_BUILT"); @@ -825,8 +825,9 @@ private static void placeCommandSign(ServerLevel world, BlockPos pos, String lab SignBlockEntity sign = (SignBlockEntity) tile; net.minecraft.network.chat.MutableComponent clickable = Component.literal(label); clickable.setStyle(Style.EMPTY.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command))); - sign.setMessage(0, clickable); - sign.setMessage(1, Component.literal("right-click")); + sign.setText(sign.getFrontText().setMessage(0, clickable) + .setMessage(1, Component.literal("right-click")), true); + sign.setWaxed(true); sign.setChanged(); } @@ -835,9 +836,9 @@ private static void placeSign(ServerLevel world, BlockPos pos, String... lines) BlockEntity tile = world.getBlockEntity(pos); if (!(tile instanceof SignBlockEntity)) return; SignBlockEntity sign = (SignBlockEntity) tile; - for (int i = 0; i < 4; i++) { - sign.setMessage(i, Component.literal(i < lines.length ? trimSign(lines[i]) : "")); - } + var text = sign.getFrontText(); + for (int i = 0; i < 4; i++) text = text.setMessage(i, Component.literal(i < lines.length ? trimSign(lines[i]) : "")); + sign.setText(text, true); sign.setChanged(); } diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksDefinitionLoader.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksDefinitionLoader.java index 891a7e1e..9125ad24 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksDefinitionLoader.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksDefinitionLoader.java @@ -38,8 +38,8 @@ static WorksDefinition loadNative117() { return load("/assets/advantageworkstest/works/works-1.17.1.json", "1.17.1"); } - static WorksDefinition loadNative119() { - return load("/assets/advantageworkstest/works/works-1.19.4.json", "1.19.4"); + static WorksDefinition loadNative1201() { + return load("/assets/advantageworkstest/works/works-1.20.1.json", "1.20.1"); } static WorksDefinition load(String resource, String minecraft) { diff --git a/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksResultWriter.java b/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksResultWriter.java index eefe3101..6b4530b0 100644 --- a/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksResultWriter.java +++ b/test-rig/src/main/java/zone/moddev/mc/advantageworks/WorksResultWriter.java @@ -31,7 +31,7 @@ File write(String stationId, String kind, Map payload) { Map document = new LinkedHashMap<>(); document.put("format", 1); document.put("recordedAtUtc", utcNow()); - document.put("minecraft", "1.19.4"); + document.put("minecraft", "1.20.1"); document.put("forge", net.minecraftforge.versions.forge.ForgeVersion.getVersion()); document.put("mods", loadedMods()); document.put("station", stationId); diff --git a/test-rig/src/main/resources/META-INF/mods.toml b/test-rig/src/main/resources/META-INF/mods.toml index 8ceb14ec..60dcefb7 100644 --- a/test-rig/src/main/resources/META-INF/mods.toml +++ b/test-rig/src/main/resources/META-INF/mods.toml @@ -1,5 +1,5 @@ modLoader="javafml" -loaderVersion="[45,46)" +loaderVersion="[47,48)" license="LGPL-3.0-only" [[mods]] @@ -12,20 +12,20 @@ description='''Server-side commissioning harness for the Advantage family. Not f [[dependencies.advantageworkstest]] modId="basepower" mandatory=true -versionRange="[2.4.11.119041,3.0.0)" +versionRange="[2.4.12.120011,3.0.0)" ordering="AFTER" side="SERVER" [[dependencies.advantageworkstest]] modId="forge" mandatory=true -versionRange="[45.4.0,46)" +versionRange="[47.4.10,48)" ordering="NONE" side="SERVER" [[dependencies.advantageworkstest]] modId="minecraft" mandatory=true -versionRange="[1.19.4]" +versionRange="[1.20.1]" ordering="NONE" side="SERVER" diff --git a/test-rig/src/main/resources/assets/advantageworkstest/works/works-1.19.4.json b/test-rig/src/main/resources/assets/advantageworkstest/works/works-1.20.1.json similarity index 52% rename from test-rig/src/main/resources/assets/advantageworkstest/works/works-1.19.4.json rename to test-rig/src/main/resources/assets/advantageworkstest/works/works-1.20.1.json index c9c2099a..d0776263 100644 --- a/test-rig/src/main/resources/assets/advantageworkstest/works/works-1.19.4.json +++ b/test-rig/src/main/resources/assets/advantageworkstest/works/works-1.20.1.json @@ -1,6 +1,6 @@ { "format": 1, - "minecraft": "1.19.4", - "title": "Advantage Works 1.19.4 Commissioning Ground", + "minecraft": "1.20.1", + "title": "Advantage Works 1.20.1 Commissioning Ground", "stationSource": "/assets/advantageworkstest/works/works-1.13.2.json" } diff --git a/test-rig/src/main/resources/pack.mcmeta b/test-rig/src/main/resources/pack.mcmeta index 40e941ce..d0d62496 100644 --- a/test-rig/src/main/resources/pack.mcmeta +++ b/test-rig/src/main/resources/pack.mcmeta @@ -1,8 +1,8 @@ { "pack": { "description": "Advantage Works 1.19.4 test resources", - "pack_format": 12, - "forge:resource_pack_format": 13, - "forge:data_pack_format": 12 + "pack_format": 15, + "forge:resource_pack_format": 15, + "forge:data_pack_format": 15 } } diff --git a/test-rig/src/runner/java/zone/moddev/mc/advantageworks/runner/WorksRunner.java b/test-rig/src/runner/java/zone/moddev/mc/advantageworks/runner/WorksRunner.java index 66639fb9..f1e20335 100644 --- a/test-rig/src/runner/java/zone/moddev/mc/advantageworks/runner/WorksRunner.java +++ b/test-rig/src/runner/java/zone/moddev/mc/advantageworks/runner/WorksRunner.java @@ -67,7 +67,7 @@ private WorksRunner() { public static void main(String[] args) throws Exception { Arguments arguments = Arguments.parse(args); - Profile profile = readNative119Profile(arguments.profile); + Profile profile = readNative1201Profile(arguments.profile); if (arguments.serverPort != null) profile.serverPort = arguments.serverPort; File testRig = findTestRig(arguments.profile); File powerRoot = testRig.getParentFile().getCanonicalFile(); @@ -316,17 +316,17 @@ static void requireModularLauncher(File runtime, String launcher) throws Excepti Path args = root.resolve(launcher); PreparedServerSeed.requirePlain(args); boolean native118 = launcher.startsWith("libraries/net/minecraftforge/forge/1.18.2-40.3.0/"); - boolean native119 = launcher.startsWith("libraries/net/minecraftforge/forge/1.19.4-45.4.0/"); + boolean native1201 = launcher.startsWith("libraries/net/minecraftforge/forge/1.20.1-47.4.10/"); Set expected = new LinkedHashSet<>(Arrays.asList( "--add-modules ALL-MODULE-PATH", "--add-opens java.base/java.util.jar=cpw.mods.securejarhandler", "--add-exports java.base/sun.security.util=cpw.mods.securejarhandler", "-DlibraryDirectory=libraries", "cpw.mods.bootstraplauncher.BootstrapLauncher", - "--launchTarget forgeserver", "--fml.forgeVersion " + (native119 ? "45.4.0" : native118 ? "40.3.0" : "37.1.1"), - "--fml.mcVersion " + (native119 ? "1.19.4" : native118 ? "1.18.2" : "1.17.1"), + "--launchTarget forgeserver", "--fml.forgeVersion " + (native1201 ? "47.4.10" : native118 ? "40.3.0" : "37.1.1"), + "--fml.mcVersion " + (native1201 ? "1.20.1" : native118 ? "1.18.2" : "1.17.1"), "--fml.forgeGroup net.minecraftforge", - "--fml.mcpVersion " + (native119 ? "20230314.122934" : native118 ? "20220404.173914" : "20210706.113038"))); - if (native118 || native119) expected.addAll(Arrays.asList( + "--fml.mcpVersion " + (native1201 ? "20230612.114412" : native118 ? "20220404.173914" : "20210706.113038"))); + if (native118 || native1201) expected.addAll(Arrays.asList( "--add-opens java.base/java.lang.invoke=cpw.mods.securejarhandler", "--add-exports jdk.naming.dns/com.sun.jndi.dns=java.naming", "-Djava.net.preferIPv6Addresses=system")); @@ -786,8 +786,8 @@ static PreparedServerSeed preparedServerSeed(File testRig, Profile profile, Argu } return new PreparedServerSeed(preparedPath(testRig, arguments.preparedServerSeed), preparedPath(testRig, arguments.preparedServerSeedInventory), arguments.preparedServerSeedSha256, - serverLauncherPath(profile), "1.19.4".equals(profile.minecraftVersion) - ? "libraries/net/minecraft/server/1.19.4-20230314.122934/server-1.19.4-20230314.122934-extra.jar" + serverLauncherPath(profile), "1.20.1".equals(profile.minecraftVersion) + ? "libraries/net/minecraft/server/1.20.1-20230612.114412/server-1.20.1-20230612.114412-extra.jar" : "1.18.2".equals(profile.minecraftVersion) ? "libraries/net/minecraft/server/1.18.2-20220404.173914/server-1.18.2-20220404.173914-extra.jar" : "1.17.1".equals(profile.minecraftVersion) @@ -1104,13 +1104,13 @@ static String serverLauncherPath(Profile profile) { private static boolean modularForge(Profile profile) { return "1.17.1".equals(profile.minecraftVersion) || "1.18.2".equals(profile.minecraftVersion) - || "1.19.4".equals(profile.minecraftVersion); + || "1.20.1".equals(profile.minecraftVersion); } private static File runtimeJavaHome(Profile profile) throws Exception { if (!modularForge(profile)) return java8Home(profile); - boolean native119 = "1.19.4".equals(profile.minecraftVersion); - boolean java17 = native119 || "1.18.2".equals(profile.minecraftVersion); + boolean native1201 = "1.20.1".equals(profile.minecraftVersion); + boolean java17 = native1201 || "1.18.2".equals(profile.minecraftVersion); String variable = java17 ? "ADVANTAGE_WORKS_JAVA17_HOME" : "ADVANTAGE_WORKS_JAVA16_HOME"; String configured = java17 ? profile.java17Home : profile.java16Home; if (configured == null || configured.trim().isEmpty()) configured = System.getenv(variable); @@ -1121,8 +1121,8 @@ private static File runtimeJavaHome(Profile profile) throws Exception { if (release.isFile()) { try (InputStream input = Files.newInputStream(release.toPath())) { metadata.load(input); } } - String javaVersion = native119 ? "17.0.1" : java17 ? "17.0.20.1" : "16.0.2"; - String temurin = native119 ? "17.0.1+12" : java17 ? "17.0.20.1+1" : "16.0.2+7"; + String javaVersion = native1201 ? "17.0.1" : java17 ? "17.0.20.1" : "16.0.2"; + String temurin = native1201 ? "17.0.1+12" : java17 ? "17.0.20.1+1" : "16.0.2+7"; if (!javaExecutable(home).isFile() || !("\"" + javaVersion + "\"").equals(metadata.getProperty("JAVA_VERSION")) || !("\"Temurin-" + temurin + "\"").equals(metadata.getProperty("IMPLEMENTOR_VERSION"))) { throw new IllegalStateException("Set " + variable + " to the pinned Temurin " + temurin + " runtime: " + home); @@ -1183,7 +1183,7 @@ private static File javaExecutable(File home) { return new File(new File(home, "bin"), windows ? "java.exe" : "java"); } - private static void writeRuntimeFiles(File runtime, Profile profile) throws Exception { + static void writeRuntimeFiles(File runtime, Profile profile) throws Exception { write(new File(runtime, "eula.txt"), "eula=true\n"); write(new File(runtime, "advantage-works.allow"), "Generated by Advantage Works runner.\n"); write(new File(runtime, "banned-ips.json"), "[]\n"); @@ -1271,14 +1271,14 @@ static Profile readNative117Profile(File file) throws Exception { return profile; } - static Profile readNative119Profile(File file) throws Exception { - Profile profile = readProfile(file, "1.19.4", "1.19.4-45.4.0"); + static Profile readNative1201Profile(File file) throws Exception { + Profile profile = readProfile(file, "1.20.1", "1.20.1-47.4.10"); if (!"UNQUALIFIED".equals(profile.qualificationStatus)) { - throw new IllegalArgumentException("The 1.19.4 destination must start UNQUALIFIED"); + throw new IllegalArgumentException("The 1.20.1 destination must start UNQUALIFIED"); } for (ModInput input : profile.mods) { - if (input.version == null || !input.version.endsWith(".119041")) { - throw new IllegalArgumentException("Non-1.19.4 destination mod version: " + input.id); + if (input.version == null || !input.version.endsWith(".120011")) { + throw new IllegalArgumentException("Non-1.20.1 destination mod version: " + input.id); } } if ("minecraft:flat".equals(profile.levelType)) { @@ -1289,7 +1289,8 @@ static Profile readNative119Profile(File file) throws Exception { "/assets/advantageworkstest/works/flat-generator.json")) { if (input == null) throw new IllegalStateException("Missing shared Works generator settings"); var settings = GSON.fromJson(new InputStreamReader(input, StandardCharsets.UTF_8), JsonObject.class); - profile.generatorSettings = GSON.toJson(settings); + // server.properties stores the generator JSON on one line. + profile.generatorSettings = settings.toString(); } } return profile; diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/ConnectedProbeObservationTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/ConnectedProbeObservationTest.java index 6d081942..0d754742 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/ConnectedProbeObservationTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/ConnectedProbeObservationTest.java @@ -89,7 +89,7 @@ private static final class ObservedChest extends ChestBlockEntity { private static final class ObservationWorld extends ServerLevel { BlockEntity tile; - private ObservationWorld() { super(null, null, null, null, null, null, null, false, 0L, List.of(), false); } + private ObservationWorld() { super(null, null, null, null, null, null, null, false, 0L, List.of(), false, null); } @Override public BlockState getBlockState(BlockPos pos) { return Blocks.CHEST.defaultBlockState(); } @Override public BlockEntity getBlockEntity(BlockPos pos) { return tile; } } diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117EntityContextTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117EntityContextTest.java index 5226f3e8..7b701af4 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117EntityContextTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117EntityContextTest.java @@ -53,7 +53,9 @@ public class Native117EntityContextTest { ServerLevel world = world(Level.NETHER); Boat vehicle = new Boat(EntityType.BOAT, world), passenger = new Boat(EntityType.BOAT, world); assertTrue(passenger.startRiding(vehicle, true)); - passenger.level = world(Level.END); + Field level = net.minecraft.world.entity.Entity.class.getDeclaredField("level"); + level.setAccessible(true); + level.set(passenger, world(Level.END)); reject(vehicle, world); } @@ -102,7 +104,7 @@ private static void set(ServerLevel world, String name, Object value) throws Exc } private static final class EntityFixtureWorld extends ServerLevel { - private EntityFixtureWorld() { super(null, null, null, null, null, null, null, false, 0L, java.util.List.of(), false); } + private EntityFixtureWorld() { super(null, null, null, null, null, null, null, false, 0L, java.util.List.of(), false, null); } @Override public net.minecraft.world.flag.FeatureFlagSet enabledFeatures() { return net.minecraft.world.flag.FeatureFlags.DEFAULT_FLAGS; diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117JoiningHoldTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117JoiningHoldTest.java index fed8aa5b..516e565f 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117JoiningHoldTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native117JoiningHoldTest.java @@ -36,7 +36,7 @@ public class Native117JoiningHoldTest { assertTrue(boat.canUpdate()); assertEquals(17, boat.tickCount); assertEquals(identity, boat.getUUID()); - assertSame(world, boat.level); + assertSame(world, boat.level()); assertFalse(boat.isRemoved()); } diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119DefinitionTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201DefinitionTest.java similarity index 90% rename from test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119DefinitionTest.java rename to test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201DefinitionTest.java index a6502b94..369f09e3 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119DefinitionTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201DefinitionTest.java @@ -6,16 +6,16 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; -public class Native119DefinitionTest { +public class Native1201DefinitionTest { @Test public void nativeTargetPreservesEverySourceStationAndDistrict() throws Exception { Gson gson = new Gson(); try (InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream( "/assets/advantageworkstest/works/works-1.13.2.json"), StandardCharsets.UTF_8)) { WorksDefinition source = gson.fromJson(reader, WorksDefinition.class); - WorksDefinition target = WorksDefinitionLoader.loadNative119(); + WorksDefinition target = WorksDefinitionLoader.loadNative1201(); assertEquals("1.13.2", source.minecraft); - assertEquals("1.19.4", target.minecraft); + assertEquals("1.20.1", target.minecraft); assertEquals(21, target.stations.size()); assertEquals(gson.toJsonTree(source.districts), gson.toJsonTree(target.districts)); assertEquals(gson.toJsonTree(source.stations), gson.toJsonTree(target.stations)); diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119PackMetadataTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201PackMetadataTest.java similarity index 67% rename from test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119PackMetadataTest.java rename to test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201PackMetadataTest.java index 3328a890..b06873da 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119PackMetadataTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201PackMetadataTest.java @@ -8,16 +8,16 @@ import org.junit.Test; import static org.junit.Assert.*; -public class Native119PackMetadataTest { - @Test public void harnessResourcesDeclareTheNative118PackFormats() throws Exception { +public class Native1201PackMetadataTest { + @Test public void harnessResourcesDeclareTheNativePackFormats() throws Exception { try (InputStream input = getClass().getResourceAsStream("/pack.mcmeta")) { assertNotNull(input); JsonObject pack = new JsonParser().parse(new InputStreamReader(input, StandardCharsets.UTF_8)) .getAsJsonObject().getAsJsonObject("pack"); assertTrue(pack.getAsJsonPrimitive("pack_format").isNumber()); - assertEquals(12, pack.get("pack_format").getAsInt()); - assertEquals(13, pack.get("forge:resource_pack_format").getAsInt()); - assertEquals(12, pack.get("forge:data_pack_format").getAsInt()); + assertEquals(15, pack.get("pack_format").getAsInt()); + assertEquals(15, pack.get("forge:resource_pack_format").getAsInt()); + assertEquals(15, pack.get("forge:data_pack_format").getAsInt()); } } } diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119TestFlatTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201TestFlatTest.java similarity index 99% rename from test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119TestFlatTest.java rename to test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201TestFlatTest.java index fd598e8e..e10d01fe 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native119TestFlatTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/Native1201TestFlatTest.java @@ -23,7 +23,7 @@ import org.junit.Test; import static org.junit.Assert.*; -public class Native119TestFlatTest { +public class Native1201TestFlatTest { private static RegistryAccess registries; @BeforeClass public static void bootstrap() { diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/NativeEntityTickGateTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/NativeEntityTickGateTest.java index f8109ecb..344bfdee 100644 --- a/test-rig/src/test/java/zone/moddev/mc/advantageworks/NativeEntityTickGateTest.java +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/NativeEntityTickGateTest.java @@ -34,7 +34,7 @@ public class NativeEntityTickGateTest { hold.restore(); actual.clear(); gate.forEach(actual::add); assertEquals(Arrays.asList(first, second), actual); - assertTrue(gate.contains(first)); assertSame(world, first.level); assertFalse(first.isRemoved()); + assertTrue(gate.contains(first)); assertSame(world, first.level()); assertFalse(first.isRemoved()); } @Test public void joinBeforeNativeRegistrationIsStillHeldAndAllOtherOperationsDelegate() throws Exception { diff --git a/test-rig/src/test/java/zone/moddev/mc/advantageworks/runner/Native1201ProfileTest.java b/test-rig/src/test/java/zone/moddev/mc/advantageworks/runner/Native1201ProfileTest.java new file mode 100644 index 00000000..a49a36d1 --- /dev/null +++ b/test-rig/src/test/java/zone/moddev/mc/advantageworks/runner/Native1201ProfileTest.java @@ -0,0 +1,32 @@ +package zone.moddev.mc.advantageworks.runner; + +import com.google.gson.JsonParser; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Properties; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import static org.junit.Assert.*; + +public class Native1201ProfileTest { + @Rule public TemporaryFolder temporary = new TemporaryFolder(); + + @Test public void flatGeneratorSettingsSurviveLoadingServerProperties() throws Exception { + var profile = WorksRunner.readNative1201Profile( + new File("profiles/native1201/packaged-optional-power.json")); + File runtime = temporary.newFolder(); + WorksRunner.writeRuntimeFiles(runtime, profile); + + Properties properties = new Properties(); + try (InputStream input = Files.newInputStream(runtime.toPath().resolve("server.properties"))) { + properties.load(input); + } + assertEquals("minecraft:flat", properties.getProperty("level-type")); + var generator = new JsonParser().parse(properties.getProperty("generator-settings")).getAsJsonObject(); + assertEquals("minecraft:plains", generator.get("biome").getAsString()); + assertEquals(3, generator.getAsJsonArray("layers").size()); + assertEquals(0, generator.getAsJsonArray("structure_overrides").size()); + } +}