From 1af078438cea068ba6ebbd83dbb759bbb0e526c1 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 11:40:13 +0000 Subject: [PATCH 1/8] Port Electric Advantage to Minecraft 1.15.2 Use native buffered renderers and block properties while retaining machine state, recipes, mining levels and the shared conduit behaviour. --- .github/workflows/ci.yml | 55 +++-- .github/workflows/codeql-analysis.yml | 41 ++-- .github/workflows/validate-gradle-build.yml | 4 +- CHANGELOG.txt | 16 ++ README.md | 35 ++-- build.gradle | 51 +++-- gradle.properties | 35 ++-- gradlew.bat | 168 +++++++-------- .../electricadvantage/ElectricAdvantage.java | 4 +- .../blocks/ElectricScaffoldBlock.java | 11 +- .../blocks/PumpPipeBlock.java | 3 +- .../graphics/BufferedQuads.java | 60 ++++++ .../graphics/ClientRegistration.java | 14 +- .../graphics/ElectricRenderTypes.java | 22 ++ .../graphics/HydroturbineRenderer.java | 38 ++-- .../graphics/LaserDrillRenderer.java | 87 +++----- .../graphics/LaserTurretRenderer.java | 108 ++++------ .../machines/ElectricCrusherTileEntity.java | 2 +- .../machines/ElectricDrillBlock.java | 2 +- .../machines/ElectricFurnaceTileEntity.java | 2 +- .../machines/LaserTurretBlock.java | 2 +- .../machines/PhotovoltaicGeneratorBlock.java | 5 - .../PhotovoltaicGeneratorTileEntity.java | 2 +- src/main/resources/META-INF/mods.toml | 4 +- .../blocks/NativeBlockContractTest.java | 82 ++++++++ .../graphics/RendererBufferContractTest.java | 193 ++++++++++++++++++ .../electricadvantage/init/VillagesTest.java | 2 +- .../resources/BuildWorkflowContractTest.java | 41 ++++ 28 files changed, 737 insertions(+), 352 deletions(-) create mode 100644 src/main/java/zone/moddev/mc/electricadvantage/graphics/BufferedQuads.java create mode 100644 src/main/java/zone/moddev/mc/electricadvantage/graphics/ElectricRenderTypes.java create mode 100644 src/test/java/zone/moddev/mc/electricadvantage/blocks/NativeBlockContractTest.java create mode 100644 src/test/java/zone/moddev/mc/electricadvantage/graphics/RendererBufferContractTest.java create mode 100644 src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8d1d27..63b6d5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,16 @@ -name: Electric Advantage 1.14 CI +name: Electric Advantage 1.15 CI on: push: - branches: [master-1.14.4, 'feature/**'] + branches: [master-1.15.2, 'feature/**'] pull_request: - branches: [master-1.14.4] + branches: [master-1.15.2] permissions: contents: read concurrency: - group: electricadvantage-1.14-${{ github.workflow }}-${{ github.ref }} + group: electricadvantage-1.15-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -21,27 +21,32 @@ jobs: steps: - name: Check out ElectricAdvantage uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - name: Use canonical LF dependency inputs + # Apply before every dependency checkout, including OreSpawn. + run: git config --global core.autocrlf false - name: Check out pinned OreSpawn uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/OreSpawn - ref: 9c2488cba02d317e3f31e24441dcc58273d8d0e6 + ref: 5613baf876747ed071cb7ad7e2aff4e0ce4f0a03 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: 713802f93f2d1f650e1593fa35c487ea43add4a5 + ref: 1d166d917663d4b4a5a88a86440adc0ae761e393 path: .ci-dependencies/BaseMetals - - name: Check out PowerAdvantage 1.14.4 + - name: Check out PowerAdvantage 1.15.2 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - ref: 1d498ca02b6795b16435f0ece35ac04c67ef6948 + ref: b15e2091e9647860bd90284aef6135a311692864 path: .ci-dependencies/PowerAdvantage + - name: Install pinned Java 25 Mavenizer runtime + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 + with: + distribution: temurin + java-version: '25.0.3+9.0.LTS' - name: Install Java 8 toolchain uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: @@ -50,11 +55,17 @@ jobs: - name: Install Java 17 for Gradle uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: - distribution: microsoft - java-version: '17' + distribution: temurin + java-version: '17.0.1+12' + - name: Use pinned build toolchains + shell: bash + run: >- + echo "GRADLE_OPTS=-Dorg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64 + -Dorg.gradle.java.installations.auto-detect=false + -Dorg.gradle.java.installations.auto-download=false" >> "$GITHUB_ENV" - name: Set up Gradle uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6 - - name: Build 1.14.4 dependency chain + - name: Build 1.15.2 dependency chain id: dependencies shell: bash run: | @@ -65,12 +76,12 @@ jobs: chmod +x "$orespawn/gradlew" "$basemetals/gradlew" "$power/gradlew" (cd "$orespawn" && ./gradlew jar --no-daemon --stacktrace) (cd "$basemetals" && ./gradlew jar --no-daemon --stacktrace) - osjar="$orespawn/build/libs-dev/OreSpawn-4.1.1.114041-deobf.jar" - bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.114041-deobf.jar" + osjar="$orespawn/build/libs-dev/OreSpawn-4.1.1.115021-deobf.jar" + bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.115021-deobf.jar" (cd "$power" && ./gradlew jar verifyReleaseDependencies \ -PbaseMetalsDeobfJar="$bmjar" -PoreSpawnDeobfJar="$osjar" \ --no-daemon --stacktrace) - powerjar="$power/build/libs-dev/PowerAdvantage-2.4.5.114041-deobf.jar" + powerjar="$power/build/libs-dev/PowerAdvantage-2.4.6.115021-deobf.jar" test -f "$osjar" && test -f "$bmjar" && test -f "$powerjar" echo "orespawn=$osjar" >> "$GITHUB_OUTPUT" echo "basemetals=$bmjar" >> "$GITHUB_OUTPUT" @@ -88,20 +99,20 @@ jobs: - name: Upload audited release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: ElectricAdvantage-1.14.4-${{ github.sha }} + name: ElectricAdvantage-1.15.2-${{ github.sha }} if-no-files-found: error retention-days: 30 path: | - build/libs/ElectricAdvantage-2.2.6.114041.jar - build/libs/ElectricAdvantage-2.2.6.114041-sources.jar - build/libs/ElectricAdvantage-2.2.6.114041-javadoc.jar + build/libs/ElectricAdvantage-2.2.7.115021.jar + build/libs/ElectricAdvantage-2.2.7.115021-sources.jar + build/libs/ElectricAdvantage-2.2.7.115021-javadoc.jar build/release/SHA256SUMS CHANGELOG.txt - name: Upload diagnostics on failure if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: ElectricAdvantage-1.14.4-diagnostics-${{ github.sha }} + name: ElectricAdvantage-1.15.2-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 8389dd9..d01e921 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,9 +2,9 @@ name: CodeQL on: push: - branches: [master-1.14.4, 'feature/**'] + branches: [master-1.15.2, 'feature/**'] pull_request: - branches: [master-1.14.4] + branches: [master-1.15.2] schedule: - cron: '59 7 * * 4' @@ -21,27 +21,32 @@ jobs: steps: - name: Check out ElectricAdvantage uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - name: Use canonical LF dependency inputs + # Apply before every dependency checkout, including OreSpawn. + run: git config --global core.autocrlf false - name: Check out pinned OreSpawn uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/OreSpawn - ref: 9c2488cba02d317e3f31e24441dcc58273d8d0e6 + ref: 5613baf876747ed071cb7ad7e2aff4e0ce4f0a03 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: 713802f93f2d1f650e1593fa35c487ea43add4a5 + ref: 1d166d917663d4b4a5a88a86440adc0ae761e393 path: .ci-dependencies/BaseMetals - - name: Check out PowerAdvantage 1.14.4 + - name: Check out PowerAdvantage 1.15.2 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - ref: 1d498ca02b6795b16435f0ece35ac04c67ef6948 + ref: b15e2091e9647860bd90284aef6135a311692864 path: .ci-dependencies/PowerAdvantage + - name: Install pinned Java 25 Mavenizer runtime + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 + with: + distribution: temurin + java-version: '25.0.3+9.0.LTS' - name: Install Java 8 toolchain uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: @@ -50,11 +55,17 @@ jobs: - name: Install Java 17 for Gradle uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: - distribution: microsoft - java-version: '17' + distribution: temurin + java-version: '17.0.1+12' + - name: Use pinned build toolchains + shell: bash + run: >- + echo "GRADLE_OPTS=-Dorg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64 + -Dorg.gradle.java.installations.auto-detect=false + -Dorg.gradle.java.installations.auto-download=false" >> "$GITHUB_ENV" - name: Set up Gradle uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6 - - name: Build 1.14.4 dependency chain + - name: Build 1.15.2 dependency chain id: dependencies shell: bash run: | @@ -65,12 +76,12 @@ jobs: chmod +x "$orespawn/gradlew" "$basemetals/gradlew" "$power/gradlew" (cd "$orespawn" && ./gradlew jar --no-daemon --stacktrace) (cd "$basemetals" && ./gradlew jar --no-daemon --stacktrace) - osjar="$orespawn/build/libs-dev/OreSpawn-4.1.1.114041-deobf.jar" - bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.114041-deobf.jar" + osjar="$orespawn/build/libs-dev/OreSpawn-4.1.1.115021-deobf.jar" + bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.115021-deobf.jar" (cd "$power" && ./gradlew jar verifyReleaseDependencies \ -PbaseMetalsDeobfJar="$bmjar" -PoreSpawnDeobfJar="$osjar" \ --no-daemon --stacktrace) - powerjar="$power/build/libs-dev/PowerAdvantage-2.4.5.114041-deobf.jar" + powerjar="$power/build/libs-dev/PowerAdvantage-2.4.6.115021-deobf.jar" test -f "$osjar" && test -f "$bmjar" && test -f "$powerjar" echo "orespawn=$osjar" >> "$GITHUB_OUTPUT" echo "basemetals=$bmjar" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/validate-gradle-build.yml b/.github/workflows/validate-gradle-build.yml index c471b09..7d47484 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.14.4 + - master-1.15.2 - 'feature/**' pull_request: branches: - - master-1.14.4 + - master-1.15.2 permissions: contents: read diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 36af649..0583268 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,19 @@ +Electric Advantage 2.2.7.115021 (local port candidate) + +- Target Minecraft 1.15.2, Forge 31.2.57 and snapshot 20200514-1.15.1/MCP 20200515.085601. +- Retain ForgeGradle 7.0.34, Gradle 9.6.1, Renamer 1.1.5 and Java 8 production bytecode. +- Pin native Power Advantage 2.4.6.115021, Base Metals 3.0.1.115021 and OreSpawn 4.1.1.115021 source/development artifacts. +- Provision pinned Java 25 Mavenizer, Java 8 production and Java 17 Gradle toolchains in CI and CodeQL. +- Use native MatrixStack/buffered entity and tile renderers, retaining the legacy vertex streams, UVs and beam orientation/full-bright behavior. +- Move the electric track's cutout layer to client setup and use Power's native-properties constructor, retaining shared conduit inheritance, states, events and connectivity without duplicated callbacks. +- Keep the photovoltaic panel solid and explicitly mark drill/turret properties non-solid, retaining their 1.14 behavior through Power's properties-respecting GUI constructor. +- Use the native short-NBT factory and renamed skylight predicate without changing saved values or solar-output arithmetic. +- Preserve registries, migration aliases, entity/tile IDs, fluids, NBT, ore mining levels, loot, recipes and discoveries; no balance changes. +- Add focused buffered-renderer geometry, UV, normals, light, control and matrix-stack regression tests. +- Native production/test compilation, all 44 unit tests, full release/dependency/artifact audits and Eclipse verification pass, with no skipped tests; actual ECJ reports zero errors (51 warnings). +- Resolve the preserved solar-panel solidness regression against pinned Power source b15e2091e9647860bd90284aef6135a311692864; retain the original assertion and add shared scaffold inheritance and non-solid drill/turret contracts. +- Packaged startup, combined runtime, graphical/manual acceptance and disposable-copy migration remain pending; not published. + Electric Advantage 2.2.6.114041 - Target Minecraft 1.14.4 and Forge 28.2.26 using native platform classes and Java 8 production bytecode. diff --git a/README.md b/README.md index 15ea4e3..8410a4b 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,33 @@ # ElectricAdvantage -**Minecraft 1.14.4 port, version 2.2.6.114041.** Native compilation and all 34 unit -tests pass, with no tests skipped. The combined-mod automated checks also cover -client resources, connected machinery, drill movement, chunk lifecycle, restart -persistence and disposable-copy migration. The +**Minecraft 1.15.2 port candidate, version 2.2.7.115021.** Local native compilation, +all 44 unit tests, full Gradle release-artifact/dependency audits and Eclipse +verification pass, with no tests skipped. Actual ECJ production compilation reports +zero errors (51 warnings). Tests include solar-panel solidness, non-solid drill and +turrets, shared scaffold properties/network inheritance and buffered renderer contracts. +Packaged startup, combined-mod runtime, graphical acceptance and disposable-copy +world migration remain pending for this target. Historical [1.14 test results](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.14.4/docs/1.14/BROADER-QUALIFICATION.md) -describe the tested scenarios and remaining limits, not a guarantee for an entire modpack. +are not 1.15 qualification evidence. Nothing has been published. -Electric Advantage adds electric machines, generation, storage, automation, and defence to Power Advantage for Minecraft 1.14.4. +Electric Advantage adds electric machines, generation, storage, automation, and defence to Power Advantage for Minecraft 1.15.2. Every crafting and vanilla smelting variant has an ingredient-triggered recipe-book discovery. See the [shared material checklist and discovery tests](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.13.2/docs/1.13/RECIPE-DISCOVERY.md) and [manufacturing progression audit](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.13.2/docs/1.13/MANUFACTURING-PROGRESSION.md). Regenerate unlock JSON after recipe changes with `node tools/generate-recipe-unlocks.js`; `check` audits recipe coverage and criteria. Custom machine and crushing recipes are not crafting-book entries. -## Building Minecraft 1.14.4 +## Building Minecraft 1.15.2 -The `master-1.14.4` build targets Forge `28.2.26`, mappings `snapshot 20190719-1.14.3`, -and MCP `20190829.143755`, using ForgeGradle `7.0.34` and Gradle `9.6.1`. -Run Gradle with Java 17; production code is compiled for Java 8. +The `master-1.15.2` build targets Forge `31.2.57`, mappings `snapshot 20200514-1.15.1`, +and MCP `20200515.085601`, using ForgeGradle `7.0.34`, Renamer `1.1.5` and Gradle `9.6.1`. +Run Gradle with Temurin `17.0.1+12`; production code uses Temurin `8.0.502+7`. +Mavenizer also needs Temurin `25.0.3+9.0.LTS`, including on a cold cache. CI explicitly +registers all three JDK paths and disables toolchain auto-detection and downloads. -Build the matching 1.14 PowerAdvantage, Base Metals and OreSpawn deobf jars first. +Build the matching 1.15 PowerAdvantage, Base Metals and OreSpawn deobf jars first. Dependency versions, checksums and the exact Power source reference belong in `gradle.properties`. Release audits reject missing or placeholder pins; do not -bypass those checks or substitute a 1.13 dependency. +bypass those checks or substitute another target's dependencies. Power Advantage +`2.4.6.115021` is pinned to source `b15e2091e9647860bd90284aef6135a311692864`. +Base Metals `3.0.1.115021` and OreSpawn `4.1.1.115021` also have exact source and SHA-256 pins. With the standard sibling layout: ```text @@ -54,7 +61,7 @@ The Eclipse resource root is `build/resources/main`, so its builder copies expan ## Compatibility -For an all-Advantage play-test, run `prepareCombinedEclipseLaunch` in the sibling PowerAdvantage checkout and select its `runClientAllAdvantage.launch`. The [native resource probe](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.14.4/test-rig/client-resources/README.md) checks models, textures and names across all three mods. Resource checks do not replace gameplay testing. +For an all-Advantage play-test, run `prepareCombinedEclipseLaunch` in the sibling PowerAdvantage checkout and select its `runClientAllAdvantage.launch`. Combined 1.15 client resources and gameplay require new target-specific evidence; resource checks do not replace gameplay testing. Automated coverage is bounded to the recorded scenarios. It does not establish every in-world GUI, rendering, sound, control or weapon interaction, multiplayer behavior, @@ -64,4 +71,4 @@ runtime or world-upgrade evidence. The implementation namespace is `zone.moddev.mc.electricadvantage`. Runtime identities, registries, tile/entity IDs, NBT, recipes, tags, OreSpawn provider IDs, and assets remain stable. Electric registers its legacy state, tile, and hydroturbine aliases with PowerAdvantage's shared migration hook. The RF- and Tech Reborn-labelled converters belong to Power Advantage and now use Forge Energy. -The historical [1.13 migration guide](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.13.2/docs/1.13/MIGRATION.md) explains the legacy conversion and backup process; the 1.14 test results above describe this port's coverage. Always make a whole-world backup before upgrading, keep the complete set of migration backups, and test only disposable copies. Check that every other mod supports the target version; these results do not qualify unrelated mods or an entire existing modpack. +The historical [1.13 migration guide](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.13.2/docs/1.13/MIGRATION.md) explains the legacy conversion and backup process; migration acceptance for 1.15 remains pending. Always make a whole-world backup before upgrading, keep the complete set of migration backups, and test only disposable copies. Check that every other mod supports the target version; historical results do not qualify this target, unrelated mods or an entire existing modpack. diff --git a/build.gradle b/build.gradle index 61ea1c2..3dbbfa1 100644 --- a/build.gradle +++ b/build.gradle @@ -94,7 +94,7 @@ minecraft { def forgeRunModClassesDirectory = layout.buildDirectory.dir('forge-run-mod-classes/main') def forgeMainOutputPath = forgeRunModClassesDirectory.get().asFile.absolutePath def mainModClasses = "${mod_id}%%${forgeMainOutputPath}${File.pathSeparator}${mod_id}%%${forgeMainOutputPath}" - def forge28RunTargets = [client: 'fmluserdevclient', server: 'fmluserdevserver', data: 'fmluserdevdata'] + def forge31RunTargets = [client: 'fmluserdevclient', server: 'fmluserdevserver', data: 'fmluserdevdata'] runs { configureEach { mainClass = 'net.minecraftforge.userdev.LaunchTesting' @@ -102,7 +102,7 @@ minecraft { systemProperty 'forge.logging.markers', 'REGISTRIES' systemProperty 'forge.logging.console.level', 'info' mods { electricadvantage { source sourceSets.main } } - environment 'target', forge28RunTargets[name] + environment 'target', forge31RunTargets[name] environment 'MCP_MAPPINGS', "${mapping_channel}_${mapping_version}" environment 'MCP_VERSION', mcp_version environment 'FORGE_VERSION', forge_version @@ -130,7 +130,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.14 launches.' + description = 'Merges classes and processed resources for Forge 1.15 launches.' dependsOn tasks.named('classes') from sourceSets.main.output into forgeRunModClassesDirectory @@ -178,18 +178,18 @@ if (!powerAdvantageDeobfJar.isFile()) { // These defaults follow the sibling MMD checkout layout. They are constants // here so another developer can override them without editing the script. def baseMetalsDeobfJar = file(providers.gradleProperty('baseMetalsDeobfJar') - .getOrElse('../../../../BaseMetals/BaseMetals 114/BaseMetals/build/libs-dev/' - + 'BaseMetals-3.0.1.114041-deobf.jar')) + .getOrElse('../../../../BaseMetals/BaseMetals 115/BaseMetals/build/libs-dev/' + + 'BaseMetals-3.0.1.115021-deobf.jar')) if (!baseMetalsDeobfJar.isFile()) { throw new GradleException("Missing Base Metals deobf jar at ${baseMetalsDeobfJar}. " - + "Build Base Metals 1.14 first, or pass -PbaseMetalsDeobfJar=.") + + "Build Base Metals 1.15 first, or pass -PbaseMetalsDeobfJar=.") } def oreSpawnDeobfJar = file(providers.gradleProperty('oreSpawnDeobfJar') - .getOrElse('../../../../MinecraftMineralogy/OS114/OreSpawn/build/libs-dev/' - + 'OreSpawn-4.1.1.114041-deobf.jar')) + .getOrElse('../../../../MinecraftMineralogy/OS115/OreSpawn/build/libs-dev/' + + 'OreSpawn-4.1.1.115021-deobf.jar')) if (!oreSpawnDeobfJar.isFile()) { throw new GradleException("Missing OreSpawn deobf jar at ${oreSpawnDeobfJar}. " - + "Build OreSpawn 1.14 first, or pass -PoreSpawnDeobfJar=.") + + "Build OreSpawn 1.15 first, or pass -PoreSpawnDeobfJar=.") } dependencies { @@ -341,14 +341,14 @@ tasks.register('verifyReleaseConfiguration') { group = 'verification' description = 'Validates release identity, target metadata, and dependency policy.' doLast { - if (project.mod_version != '2.2.6.114041') { + if (project.mod_version != '2.2.7.115021') { throw new GradleException("Unexpected ElectricAdvantage release version: ${project.mod_version}") } - if (project.minecraft_version != '1.14.4' - || project.forge_version != '28.2.26' + if (project.minecraft_version != '1.15.2' + || project.forge_version != '31.2.57' || project.mapping_channel != 'snapshot' - || project.mapping_version != '20190719-1.14.3' - || project.mcp_version != '20190829.143755') { + || project.mapping_version != '20200514-1.15.1' + || project.mcp_version != '20200515.085601') { throw new GradleException('Unexpected Minecraft, Forge, or mappings target') } if (project.loader_name != 'forge' || project.loader_code != '1' @@ -366,24 +366,33 @@ tasks.register('verifyReleaseConfiguration') { } if (project.cf_requirements != 'power-advantage,base-metals' || project.cf_optionals != '' - || project.cf_versions != '1.14.4') { + || project.cf_versions != '1.15.2') { throw new GradleException('Unexpected CurseForge dependency or game-version metadata') } - if (project.poweradvantage_version != '2.4.5.114041' + if (project.poweradvantage_version != '2.4.6.115021' || project.poweradvantage_source_repository != 'MinecraftModDevelopmentMods/PowerAdvantage' - || !(project.poweradvantage_source_ref ==~ /[a-f0-9]{40}/) - || !(project.poweradvantage_deobf_sha256 ==~ /[A-F0-9]{64}/)) { + || project.poweradvantage_source_ref != 'b15e2091e9647860bd90284aef6135a311692864' + || project.poweradvantage_deobf_sha256 != '2C3ADBCA79859DFA2C14EF8DC9068BF9F202D72FDB1D37B51ED4DE1B5B7E866A') { throw new GradleException('Unexpected PowerAdvantage compile dependency identity') } + if (project.basemetals_version != '3.0.1.115021' + || project.orespawn_version != '4.1.1.115021' + || project.basemetals_source_commit != '1d166d917663d4b4a5a88a86440adc0ae761e393' + || project.orespawn_source_commit != '5613baf876747ed071cb7ad7e2aff4e0ce4f0a03' + || project.basemetals_deobf_sha256 != 'A98EAC370D908F14103DB6D064C738160161FDD7203F30905562B23EEE265210' + || project.orespawn_deobf_sha256 != '358B13375A4B60622C491D6729290971A446FF14D524A600CA13710934DB3FDC' + || project.forge_installer_sha256 != '84FD49A743978421B26F62AC78222289FE892A46F996CF11CB5E05B7441A7773') { + throw new GradleException('Unexpected native dependency pins') + } String mainSource = file( 'src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java').getText('UTF-8') if (!mainSource.contains('MODID = "electricadvantage"') - || !mainSource.contains('VERSION = "2.2.6.114041"')) { + || !mainSource.contains('VERSION = "2.2.7.115021"')) { throw new GradleException('ElectricAdvantage source identity changed') } String metadata = file('src/main/resources/META-INF/mods.toml').getText('UTF-8').replace('\r\n', '\n') ['modId="electricadvantage"', 'modId="poweradvantage"', 'modId="basemetals"', - 'versionRange="[2.4.5.114041,3.0.0)"'].each { marker -> + 'versionRange="[2.4.6.115021,3.0.0)"'].each { marker -> if (!metadata.contains(marker)) { throw new GradleException("Source mods.toml is missing ${marker}") } @@ -417,7 +426,7 @@ tasks.register('verifyReleaseDependencies') { } def manifest = new Manifest(zip.getInputStream(zip.getEntry('META-INF/MANIFEST.MF'))).mainAttributes if (manifest.getValue('Implementation-Version') != project.poweradvantage_version - || manifest.getValue('Built-On') != '1.14.4-28.2.26') { + || manifest.getValue('Built-On') != '1.15.2-31.2.57') { throw new GradleException('PowerAdvantage dependency manifest has the wrong version') } } diff --git a/gradle.properties b/gradle.properties index 24cf92d..0bceb64 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,14 +5,15 @@ org.gradle.caching=true org.gradle.parallel=false net.minecraftforge.gradle.merge-source-sets=false -minecraft_version=1.14.4 -minecraft_version_range=[1.14.4] -forge_version=28.2.26 -forge_version_range=[28,) -loader_version_range=[28,) +minecraft_version=1.15.2 +minecraft_version_range=[1.15.2] +forge_version=31.2.57 +forge_installer_sha256=84FD49A743978421B26F62AC78222289FE892A46F996CF11CB5E05B7441A7773 +forge_version_range=[31.2.57,32) +loader_version_range=[31,) mapping_channel=snapshot -mapping_version=20190719-1.14.3 -mcp_version=20190829.143755 +mapping_version=20200514-1.15.1 +mcp_version=20200515.085601 loader_name=forge loader_code=1 @@ -25,23 +26,25 @@ curseforge_project_id=240985 mod_id=electricadvantage mod_name=Electric Advantage mod_license=GPL-3.0-only -mod_version=2.2.6.114041 +mod_version=2.2.7.115021 mod_group=zone.moddev.mc.electricadvantage mod_authors=DrCyano mod_description=Electric-powered machines and infrastructure for the Power Advantage platform. cf_requirements=power-advantage,base-metals cf_optionals= -cf_versions=1.14.4 +cf_versions=1.15.2 -poweradvantage_version=2.4.5.114041 +poweradvantage_version=2.4.6.115021 poweradvantage_source_repository=MinecraftModDevelopmentMods/PowerAdvantage # Exact Power Advantage source and development jar used by local and CI builds. -poweradvantage_source_ref=1d498ca02b6795b16435f0ece35ac04c67ef6948 -poweradvantage_deobf_sha256=8D8831D54B700FBFB2B9C43EE3D8D70D2B7E57185A4DBDF12202C47D5E387B39 +poweradvantage_source_ref=b15e2091e9647860bd90284aef6135a311692864 +poweradvantage_deobf_sha256=2C3ADBCA79859DFA2C14EF8DC9068BF9F202D72FDB1D37B51ED4DE1B5B7E866A -basemetals_version=3.0.1.114041 -basemetals_deobf_sha256=A14A87E3BF30964F901E715A9B4EF2F1E7317ABE7F9ACEBE60D8E6A900CA6EB2 +basemetals_version=3.0.1.115021 +basemetals_source_commit=1d166d917663d4b4a5a88a86440adc0ae761e393 +basemetals_deobf_sha256=A98EAC370D908F14103DB6D064C738160161FDD7203F30905562B23EEE265210 -orespawn_version=4.1.1.114041 -orespawn_deobf_sha256=1807C3A43F6E854F4EC5741F75A52750B733CD81DC588CF0F666C6C3A489FBEF +orespawn_version=4.1.1.115021 +orespawn_source_commit=5613baf876747ed071cb7ad7e2aff4e0ce4f0a03 +orespawn_deobf_sha256=358B13375A4B60622C491D6729290971A446FF14D524A600CA13710934DB3FDC diff --git a/gradlew.bat b/gradlew.bat index e95643d..f955316 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,84 +1,84 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java b/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java index 4083a99..0948129 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java @@ -33,12 +33,12 @@ import zone.moddev.mc.electricadvantage.recipe.RecipeConditions; import zone.moddev.mc.electricadvantage.migration.ElectricLegacyMigrations; -/** Forge 1.14 entry point for Electric Advantage. */ +/** Forge 1.15 entry point for Electric Advantage. */ @Mod(ElectricAdvantage.MODID) public final class ElectricAdvantage { public static final String MODID = "electricadvantage"; public static final String NAME = "Electric Advantage"; - public static final String VERSION = "2.2.6.114041"; + public static final String VERSION = "2.2.7.115021"; public static final Logger LOGGER = LogManager.getLogger(MODID); public static ElectricAdvantage INSTANCE; diff --git a/src/main/java/zone/moddev/mc/electricadvantage/blocks/ElectricScaffoldBlock.java b/src/main/java/zone/moddev/mc/electricadvantage/blocks/ElectricScaffoldBlock.java index 919dded..df6a451 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/blocks/ElectricScaffoldBlock.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/blocks/ElectricScaffoldBlock.java @@ -1,6 +1,6 @@ package zone.moddev.mc.electricadvantage.blocks; -import net.minecraft.util.BlockRenderLayer; +import cyano.poweradvantage.api.simple.BlockSimplePowerConduit; import net.minecraft.block.material.Material; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; @@ -11,11 +11,12 @@ import zone.moddev.mc.electricadvantage.init.Power; /** Full-block electric track/scaffold with conduit behavior. */ -public class ElectricScaffoldBlock extends cyano.poweradvantage.api.simple.BlockSimplePowerConduit { - public ElectricScaffoldBlock() { super(Material.PISTON, 0.75F, 2.0F / 16.0F, Power.ELECTRIC_POWER); } +public class ElectricScaffoldBlock extends BlockSimplePowerConduit { + public ElectricScaffoldBlock() { + super(Properties.create(Material.PISTON).hardnessAndResistance(0.75F).notSolid(), + 2.0F / 16.0F, Power.ELECTRIC_POWER); + } @Override public VoxelShape getShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) { return VoxelShapes.fullCube(); } @Override public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) { return VoxelShapes.fullCube(); } @Override public boolean isNormalCube(BlockState state, IBlockReader world, BlockPos pos) { return false; } - @Override public boolean isSolid(BlockState state) { return false; } - @Override public BlockRenderLayer getRenderLayer() { return BlockRenderLayer.CUTOUT; } } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/blocks/PumpPipeBlock.java b/src/main/java/zone/moddev/mc/electricadvantage/blocks/PumpPipeBlock.java index 5a476fe..0da6a78 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/blocks/PumpPipeBlock.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/blocks/PumpPipeBlock.java @@ -17,11 +17,10 @@ /** Hidden pump intake column. */ public class PumpPipeBlock extends Block { private static final VoxelShape SHAPE = VoxelShapes.create(0.25D, 0.0D, 0.25D, 0.75D, 1.0D, 0.75D); - public PumpPipeBlock() { super(Properties.create(Material.IRON).hardnessAndResistance(5.0F, 10.0F).variableOpacity().noDrops()); } + public PumpPipeBlock() { super(Properties.create(Material.IRON).hardnessAndResistance(5.0F, 10.0F).variableOpacity().notSolid().noDrops()); } @Override public VoxelShape getShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) { return SHAPE; } @Override public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) { return SHAPE; } @Override public boolean isNormalCube(BlockState state, IBlockReader world, BlockPos pos) { return false; } - @Override public boolean isSolid(BlockState state) { return false; } @Override public java.util.List getDrops(BlockState state, LootContext.Builder context) { return java.util.Collections.emptyList(); } @Override diff --git a/src/main/java/zone/moddev/mc/electricadvantage/graphics/BufferedQuads.java b/src/main/java/zone/moddev/mc/electricadvantage/graphics/BufferedQuads.java new file mode 100644 index 0000000..4b93ab1 --- /dev/null +++ b/src/main/java/zone/moddev/mc/electricadvantage/graphics/BufferedQuads.java @@ -0,0 +1,60 @@ +package zone.moddev.mc.electricadvantage.graphics; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; + +/** Preserves the legacy quad coordinates and UVs in the native entity vertex format. */ +final class BufferedQuads { + private final MatrixStack.Entry transform; + private final IVertexBuilder buffer; + private final int light; + private final int overlay; + private final float[][] vertices = new float[4][5]; + private int count; + + BufferedQuads(MatrixStack matrices, IVertexBuilder buffer, int light, int overlay) { + this.transform = matrices.getLast(); + this.buffer = buffer; + this.light = light; + this.overlay = overlay; + } + + BufferedQuads pos(double x, double y, double z) { + vertices[count][0] = (float) x; + vertices[count][1] = (float) y; + vertices[count][2] = (float) z; + return this; + } + + BufferedQuads tex(float u, float v) { + vertices[count][3] = u; + vertices[count][4] = v; + return this; + } + + void endVertex() { + if (++count != 4) return; + float ax = vertices[1][0] - vertices[0][0]; + float ay = vertices[1][1] - vertices[0][1]; + float az = vertices[1][2] - vertices[0][2]; + float bx = vertices[2][0] - vertices[0][0]; + float by = vertices[2][1] - vertices[0][1]; + float bz = vertices[2][2] - vertices[0][2]; + float nx = ay * bz - az * by; + float ny = az * bx - ax * bz; + float nz = ax * by - ay * bx; + float length = (float) Math.sqrt(nx * nx + ny * ny + nz * nz); + if (length > 0) { + nx /= length; + ny /= length; + nz /= length; + } + for (float[] vertex : vertices) { + buffer.pos(transform.getMatrix(), vertex[0], vertex[1], vertex[2]) + .color(255, 255, 255, 255).tex(vertex[3], vertex[4]) + .overlay(overlay).lightmap(light) + .normal(transform.getNormal(), nx, ny, nz).endVertex(); + } + count = 0; + } +} diff --git a/src/main/java/zone/moddev/mc/electricadvantage/graphics/ClientRegistration.java b/src/main/java/zone/moddev/mc/electricadvantage/graphics/ClientRegistration.java index a870c6c..c9e8038 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/graphics/ClientRegistration.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/graphics/ClientRegistration.java @@ -3,17 +3,19 @@ import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import zone.moddev.mc.electricadvantage.entities.HydroturbineEntity; -import zone.moddev.mc.electricadvantage.machines.ElectricDrillTileEntity; -import zone.moddev.mc.electricadvantage.machines.LaserTurretTileEntity; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderTypeLookup; +import zone.moddev.mc.electricadvantage.init.Blocks; +import zone.moddev.mc.electricadvantage.init.Entities; /** Client-only renderer registration. */ public final class ClientRegistration { private ClientRegistration() {} public static void onClientSetup(FMLClientSetupEvent event) { - ClientRegistry.bindTileEntitySpecialRenderer(ElectricDrillTileEntity.class, new LaserDrillRenderer()); - ClientRegistry.bindTileEntitySpecialRenderer(LaserTurretTileEntity.class, new LaserTurretRenderer()); - RenderingRegistry.registerEntityRenderingHandler(HydroturbineEntity.class, HydroturbineRenderer::new); + RenderTypeLookup.setRenderLayer(Blocks.electric_track, RenderType.getCutout()); + ClientRegistry.bindTileEntityRenderer(Entities.ELECTRIC_DRILL, LaserDrillRenderer::new); + ClientRegistry.bindTileEntityRenderer(Entities.LASER_TURRET, LaserTurretRenderer::new); + RenderingRegistry.registerEntityRenderingHandler(Entities.HYDROTURBINE, HydroturbineRenderer::new); } } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/graphics/ElectricRenderTypes.java b/src/main/java/zone/moddev/mc/electricadvantage/graphics/ElectricRenderTypes.java new file mode 100644 index 0000000..292ecc8 --- /dev/null +++ b/src/main/java/zone/moddev/mc/electricadvantage/graphics/ElectricRenderTypes.java @@ -0,0 +1,22 @@ +package zone.moddev.mc.electricadvantage.graphics; + +import net.minecraft.client.renderer.RenderState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; + +/** Scoped render state replaces the old global lighting/blending mutations. */ +final class ElectricRenderTypes extends RenderState { + private ElectricRenderTypes() { + super("electricadvantage", () -> {}, () -> {}); + } + + static RenderType unshaded(ResourceLocation texture, boolean translucent) { + return RenderType.makeType("electricadvantage_unshaded", DefaultVertexFormats.ENTITY, + 7, 256, false, translucent, RenderType.State.getBuilder() + .texture(new TextureState(texture, false, false)) + .transparency(translucent ? TRANSLUCENT_TRANSPARENCY : NO_TRANSPARENCY) + .diffuseLighting(DIFFUSE_LIGHTING_DISABLED).cull(CULL_DISABLED) + .lightmap(LIGHTMAP_ENABLED).overlay(OVERLAY_ENABLED).build(false)); + } +} diff --git a/src/main/java/zone/moddev/mc/electricadvantage/graphics/HydroturbineRenderer.java b/src/main/java/zone/moddev/mc/electricadvantage/graphics/HydroturbineRenderer.java index f025e78..eefef1f 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/graphics/HydroturbineRenderer.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/graphics/HydroturbineRenderer.java @@ -2,13 +2,13 @@ import zone.moddev.mc.electricadvantage.ElectricAdvantage; import zone.moddev.mc.electricadvantage.entities.HydroturbineEntity; -import com.mojang.blaze3d.platform.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.BufferBuilder; +import com.mojang.blaze3d.matrix.MatrixStack; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraftforge.api.distmarker.Dist; @@ -25,18 +25,12 @@ public HydroturbineRenderer(final EntityRendererManager rm) { } @Override - public void doRender(final HydroturbineEntity entity, final double x, final double y, final double z, final float scale, final float partialTick) { + public void render(final HydroturbineEntity entity, final float entityYaw, final float partialTick, + final MatrixStack matrices, final IRenderTypeBuffer buffers, final int packedLight) { { final float pixel = 1.0f / 16; HydroturbineEntity e = (HydroturbineEntity)entity; - GlStateManager.pushMatrix(); - this.bindEntityTexture(e); - GlStateManager.translatef((float)x, (float)y, (float)z); - GlStateManager.enableRescaleNormal(); - // final float scale = this.scale; - // GlStateManager.scale(scale / 1.0f, scale / 1.0f, scale / 1.0f); - final Tessellator instance = Tessellator.getInstance(); - final BufferBuilder worldRenderer = instance.getBuffer(); + matrices.push(); final float topHeight = 0.5f; final float bottomHeight = 0.375f-0.5f; final float radius = pixel; @@ -45,10 +39,10 @@ public void doRender(final HydroturbineEntity entity, final double x, final doub final float shaftMaxU = 0.5f+2*pixel; final float shaftMaxV = 1.0f; - GlStateManager.translatef(0f, 0.5f, 0f); - GlStateManager.rotatef(e.rotationYaw, 0.0f, 1.0f, 0.0f); - this.bindTexture(this.getEntityTexture(e)); - worldRenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + matrices.translate(0f, 0.5f, 0f); + matrices.rotate(Vector3f.YP.rotationDegrees(e.rotationYaw)); + final BufferedQuads worldRenderer = new BufferedQuads(matrices, + buffers.getBuffer(RenderType.getEntitySolid(texture)), packedLight, OverlayTexture.NO_OVERLAY); // render shaft worldRenderer.pos(+radius, bottomHeight, -radius).tex(shaftMinU,shaftMinV).endVertex(); @@ -179,16 +173,14 @@ public void doRender(final HydroturbineEntity entity, final double x, final doub worldRenderer.pos(cos3b*bladeOffset, sin3b*bladeOffset, depthDelta-axelLength).tex(bladeMinU,bladeMinV).endVertex(); // inner, leading - instance.draw(); - GlStateManager.disableRescaleNormal(); - GlStateManager.popMatrix(); - super.doRender(e, x, y, z, scale, partialTick); + matrices.pop(); + super.render(e, entityYaw, partialTick, matrices, buffers, packedLight); } } @Override - protected ResourceLocation getEntityTexture(final HydroturbineEntity e) { + public ResourceLocation getEntityTexture(final HydroturbineEntity e) { return texture; } } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserDrillRenderer.java b/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserDrillRenderer.java index b22bf95..7927ec1 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserDrillRenderer.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserDrillRenderer.java @@ -2,16 +2,14 @@ import zone.moddev.mc.electricadvantage.ElectricAdvantage; import zone.moddev.mc.electricadvantage.machines.ElectricDrillTileEntity; -import com.mojang.blaze3d.platform.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.BufferBuilder; +import com.mojang.blaze3d.matrix.MatrixStack; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Vector3f; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.tileentity.TileEntity; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -20,43 +18,29 @@ public class LaserDrillRenderer extends TileEntityRenderer 0){ - this.bindTexture(texture); - final Tessellator tessellator = Tessellator.getInstance(); - - final BufferBuilder worldRenderer = tessellator.getBuffer(); - final float laserU0 = 0; final float laserU1 = 0; final float laserV0 = 1.0f; final float laserV1 = 1.0f; - final float radius = 0.25f; final float laserRadius = 0.125f; - float tickRemainder = 1 - partialTick; Direction dir = e.getFacing(); float rotY = 0, rotX = 0; @@ -91,16 +75,12 @@ private void render(ElectricDrillTileEntity e, World world, BlockPos pos, float } } - GlStateManager.disableLighting(); - - GlStateManager.translatef(0.5f, 0.5f, 0.5f); - GlStateManager.rotatef(rotY, 0.0f, 1.0f, 0.0f); - GlStateManager.rotatef(rotX, 1.0f, 0.0f, 0.0f); - - int lightValue = 15 << 20 | 15 << 4; - int lmapX = lightValue >> 16 & 0xFFFF; - int lmapY = lightValue & 0xFFFF; - worldRenderer.begin(7, DefaultVertexFormats.POSITION_TEX_LMAP_COLOR); + matrices.push(); + matrices.translate(0.5f, 0.5f, 0.5f); + matrices.rotate(Vector3f.YP.rotationDegrees(rotY)); + matrices.rotate(Vector3f.XP.rotationDegrees(rotX)); + final BufferedQuads worldRenderer = new BufferedQuads(matrices, + buffers.getBuffer(beamType), 15 << 20 | 15 << 4, packedOverlay); final double x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4; x1 = 0; @@ -117,29 +97,28 @@ private void render(ElectricDrillTileEntity e, World world, BlockPos pos, float y4 = 0; z4 = z2; - worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV0).endVertex(); - worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV0).endVertex(); - worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV0).endVertex(); - worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV0).endVertex(); - tessellator.draw(); - GlStateManager.enableLighting(); + matrices.pop(); } } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserTurretRenderer.java b/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserTurretRenderer.java index b4506ab..aab7ae9 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserTurretRenderer.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/graphics/LaserTurretRenderer.java @@ -2,17 +2,13 @@ import zone.moddev.mc.electricadvantage.ElectricAdvantage; import zone.moddev.mc.electricadvantage.machines.LaserTurretTileEntity; -import net.minecraft.client.Minecraft; -import com.mojang.blaze3d.platform.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.BufferBuilder; +import com.mojang.blaze3d.matrix.MatrixStack; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Vector3f; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.tileentity.TileEntity; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -21,28 +17,16 @@ public class LaserTurretRenderer extends TileEntityRenderer 0){ final double x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4; x1 = 0; @@ -141,40 +110,33 @@ private void render(LaserTurretTileEntity e, World world, BlockPos pos, float pa y4 = 0; z4 = z2; - GlStateManager.disableLighting(); - - int lightValue = 15 << 20 | 15 << 4; - int lmapX = lightValue >> 16 & 0xFFFF; - int lmapY = lightValue & 0xFFFF; - worldRenderer.begin(7, DefaultVertexFormats.POSITION_TEX_LMAP_COLOR); + worldRenderer = new BufferedQuads(matrices, + buffers.getBuffer(renderType), 15 << 20 | 15 << 4, packedOverlay); - worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV0).endVertex(); - worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x1, y2, z1).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x2, y2, z2).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x2, y1, z2).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x1, y1, z1).tex(laserU0, laserV0).endVertex(); - worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - - worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV1).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); - worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV0).lightmap(lmapX, lmapY).color(1f, 1f, 1f, 1f).endVertex(); + worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV0).endVertex(); - tessellator.draw(); + worldRenderer.pos( x4, y3, z3).tex(laserU0, laserV1).endVertex(); + worldRenderer.pos( x4, y4, z4).tex(laserU1, laserV1).endVertex(); + worldRenderer.pos( x3, y4, z4).tex(laserU1, laserV0).endVertex(); + worldRenderer.pos( x3, y3, z3).tex(laserU0, laserV0).endVertex(); - GlStateManager.enableLighting(); } - RenderHelper.enableStandardItemLighting(); + matrices.pop(); } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricCrusherTileEntity.java b/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricCrusherTileEntity.java index 16be176..af1ea24 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricCrusherTileEntity.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricCrusherTileEntity.java @@ -103,7 +103,7 @@ public float[] getProgress() { protected void saveTo(CompoundNBT tagRoot) { ListNBT times = new ListNBT(); for(int i = 0; i < numberOfInputSlots(); i++){ - times.add(new ShortNBT(smashTime[i])); + times.add(ShortNBT.valueOf(smashTime[i])); } tagRoot.put("smashTime", times); } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricDrillBlock.java b/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricDrillBlock.java index bd1aac5..d2b25dc 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricDrillBlock.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricDrillBlock.java @@ -33,7 +33,7 @@ public class ElectricDrillBlock extends GUIBlock implements ITypedConduit { private final ConduitType[] types = {Power.ELECTRIC_POWER}; public ElectricDrillBlock() { - super(Block.Properties.create(Material.PISTON).hardnessAndResistance(0.75F).variableOpacity()); + super(Block.Properties.create(Material.PISTON).hardnessAndResistance(0.75F).variableOpacity().notSolid()); setDefaultState(getStateContainer().getBaseState() .with(ACTIVE, false) .with(FACING, Direction.DOWN)); diff --git a/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricFurnaceTileEntity.java b/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricFurnaceTileEntity.java index 99f7146..5443c02 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricFurnaceTileEntity.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/machines/ElectricFurnaceTileEntity.java @@ -99,7 +99,7 @@ public float[] getProgress() { protected void saveTo(CompoundNBT tagRoot) { ListNBT burnTimes = new ListNBT(); for(int i = 0; i < numberOfInputSlots(); i++){ - burnTimes.add(new ShortNBT(burnTime[i])); + burnTimes.add(ShortNBT.valueOf(burnTime[i])); } tagRoot.put("cookTime", burnTimes); } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/machines/LaserTurretBlock.java b/src/main/java/zone/moddev/mc/electricadvantage/machines/LaserTurretBlock.java index d7809b8..2dbd918 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/machines/LaserTurretBlock.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/machines/LaserTurretBlock.java @@ -25,7 +25,7 @@ public class LaserTurretBlock extends ElectricMachineBlock { public final boolean evil; public LaserTurretBlock(boolean isEvil) { super(Block.Properties.create(Material.PISTON) - .hardnessAndResistance(5.0F, 100.0F).variableOpacity()); + .hardnessAndResistance(5.0F, 100.0F).variableOpacity().notSolid()); this.evil = isEvil; } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorBlock.java b/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorBlock.java index 1f633f4..5a13ffd 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorBlock.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorBlock.java @@ -24,11 +24,6 @@ public boolean isNormalCube(BlockState bs, net.minecraft.world.IBlockReader worl return true; } - @Override - public boolean isSolid(BlockState bs) - { - return true; - } } diff --git a/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorTileEntity.java b/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorTileEntity.java index 660b8bb..b073198 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorTileEntity.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/machines/PhotovoltaicGeneratorTileEntity.java @@ -93,7 +93,7 @@ public void powerUpdate(){ public static float getLightIntensityAt(BlockPos pos, World w){ float light; - if(w.isSkyLightMax(pos) && w.dimension.hasSkyLight()){ + if(w.canSeeSky(pos) && w.dimension.hasSkyLight()){ // outdoor light imposes no penalty light = MathHelper.sin((float)w.getDayTime() * 2.61799E-4f); // (worldTime * pi / 12000); // handle weather diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 3ffdfdc..863503a 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -30,13 +30,13 @@ side="BOTH" [[dependencies.electricadvantage]] modId="poweradvantage" mandatory=true -versionRange="[2.4.5.114041,3.0.0)" +versionRange="[2.4.6.115021,3.0.0)" ordering="AFTER" side="BOTH" [[dependencies.electricadvantage]] modId="basemetals" mandatory=false -versionRange="[3.0.1.114041,4.0.0)" +versionRange="[3.0.1.115021,4.0.0)" ordering="AFTER" side="BOTH" diff --git a/src/test/java/zone/moddev/mc/electricadvantage/blocks/NativeBlockContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/blocks/NativeBlockContractTest.java new file mode 100644 index 0000000..9167151 --- /dev/null +++ b/src/test/java/zone/moddev/mc/electricadvantage/blocks/NativeBlockContractTest.java @@ -0,0 +1,82 @@ +package zone.moddev.mc.electricadvantage.blocks; + +import cyano.poweradvantage.api.ConduitBlock; +import cyano.poweradvantage.api.PowerConnectorContext; +import cyano.poweradvantage.api.simple.BlockSimplePowerConduit; +import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.pathfinding.PathType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.util.registry.Bootstrap; +import net.minecraft.world.Explosion; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; +import org.junit.BeforeClass; +import org.junit.Test; +import zone.moddev.mc.electricadvantage.init.Power; +import zone.moddev.mc.electricadvantage.machines.ElectricDrillBlock; +import zone.moddev.mc.electricadvantage.machines.LaserTurretBlock; +import zone.moddev.mc.electricadvantage.machines.PhotovoltaicGeneratorBlock; +import static org.junit.Assert.*; + +public class NativeBlockContractTest { + @BeforeClass public static void bootstrapNativeRegistries() { Bootstrap.register(); } + + @Test public void scaffoldRetainsNonSolidFullCollisionAndSharedStateProperties() { + ElectricScaffoldBlock block = new ElectricScaffoldBlock(); + BlockState state = block.getDefaultState(); + assertFalse(state.isSolid()); + assertFalse(block.isNormalCube(state, null, BlockPos.ZERO)); + assertEquals(VoxelShapes.fullCube().getBoundingBox(), + block.getCollisionShape(state, null, BlockPos.ZERO, ISelectionContext.dummy()).getBoundingBox()); + assertEquals(6, state.getProperties().size()); + assertSame(BlockSimplePowerConduit.NORTH, ElectricScaffoldBlock.NORTH); + assertSame(BlockSimplePowerConduit.SOUTH, ElectricScaffoldBlock.SOUTH); + assertSame(BlockSimplePowerConduit.EAST, ElectricScaffoldBlock.EAST); + assertSame(BlockSimplePowerConduit.WEST, ElectricScaffoldBlock.WEST); + assertSame(BlockSimplePowerConduit.UP, ElectricScaffoldBlock.UP); + assertSame(BlockSimplePowerConduit.DOWN, ElectricScaffoldBlock.DOWN); + for (PathType type : PathType.values()) assertFalse(block.allowsMovement(state, null, BlockPos.ZERO, type)); + } + + @Test public void scaffoldInheritsSharedPlacementAndNetworkCallbacks() throws Exception { + Class scaffold = ElectricScaffoldBlock.class; + assertSame(BlockSimplePowerConduit.class, scaffold.getSuperclass()); + assertSame(BlockSimplePowerConduit.class, + scaffold.getMethod("getStateForPlacement", BlockItemUseContext.class).getDeclaringClass()); + assertSame(BlockSimplePowerConduit.class, + scaffold.getMethod("updatePostPlacement", BlockState.class, Direction.class, BlockState.class, + IWorld.class, BlockPos.class, BlockPos.class).getDeclaringClass()); + assertSame(BlockSimplePowerConduit.class, + scaffold.getMethod("canAcceptConnection", PowerConnectorContext.class).getDeclaringClass()); + assertSame(ConduitBlock.class, + scaffold.getMethod("onBlockAdded", BlockState.class, World.class, BlockPos.class, + BlockState.class, boolean.class).getDeclaringClass()); + assertSame(ConduitBlock.class, + scaffold.getMethod("onReplaced", BlockState.class, World.class, BlockPos.class, + BlockState.class, boolean.class).getDeclaringClass()); + assertSame(ConduitBlock.class, + scaffold.getMethod("onExplosionDestroy", World.class, BlockPos.class, Explosion.class).getDeclaringClass()); + ElectricScaffoldBlock block = new ElectricScaffoldBlock(); + assertEquals(1, block.getTypes().length); + assertSame(Power.ELECTRIC_POWER, block.getTypes()[0]); + assertFalse(block.isPowerSink(Power.ELECTRIC_POWER)); + assertFalse(block.isPowerSource(Power.ELECTRIC_POWER)); + } + + @Test public void customMachinePropertiesKeepDrillAndBothTurretsNonSolid() { + assertFalse(new ElectricDrillBlock().getDefaultState().isSolid()); + assertFalse(new LaserTurretBlock(false).getDefaultState().isSolid()); + assertFalse(new LaserTurretBlock(true).getDefaultState().isSolid()); + } + + @Test public void hiddenPumpPipeRemainsNonSolidAndSolarPanelRemainsSolid() { + assertFalse(new PumpPipeBlock().getDefaultState().isSolid()); + PhotovoltaicGeneratorBlock panel = new PhotovoltaicGeneratorBlock(); + assertTrue("The 1.14 photovoltaic block explicitly overrides isSolid to true", panel.getDefaultState().isSolid()); + assertTrue(panel.isNormalCube(panel.getDefaultState(), null, BlockPos.ZERO)); + } +} diff --git a/src/test/java/zone/moddev/mc/electricadvantage/graphics/RendererBufferContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/graphics/RendererBufferContractTest.java new file mode 100644 index 0000000..8e8e423 --- /dev/null +++ b/src/test/java/zone/moddev/mc/electricadvantage/graphics/RendererBufferContractTest.java @@ -0,0 +1,193 @@ +package zone.moddev.mc.electricadvantage.graphics; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.util.Direction; +import net.minecraft.util.registry.Bootstrap; +import org.junit.BeforeClass; +import org.junit.Test; +import sun.misc.Unsafe; +import zone.moddev.mc.electricadvantage.init.Power; +import zone.moddev.mc.electricadvantage.machines.ElectricDrillTileEntity; +import zone.moddev.mc.electricadvantage.machines.LaserTurretTileEntity; +import cyano.poweradvantage.api.ConduitType; +import cyano.poweradvantage.api.simple.TileEntitySimplePowerMachine; + +import static org.junit.Assert.*; + +public class RendererBufferContractTest { + private static final int FULL_BRIGHT = 15 << 20 | 15 << 4; + + @BeforeClass public static void bootstrapNativeRegistries() { + Bootstrap.register(); + } + + @Test public void quadNormalsUseWindingAndTheNativeNormalMatrix() { + MatrixStack matrices = new MatrixStack(); + matrices.translate(3, 4, 5); + matrices.rotate(Vector3f.YP.rotationDegrees(90)); + RecordingBuffer buffer = new RecordingBuffer(); + BufferedQuads quads = new BufferedQuads(matrices, buffer, 0x123456, 0x789abc); + quad(quads, false); + quad(quads, true); + assertEquals(8, buffer.vertices.size()); + Vertex first = buffer.vertices.get(0); + assertArrayEquals(new float[] {3, 4, 5}, first.position, 0.00001F); + assertArrayEquals(new float[] {1, 0, 0}, first.normal, 0.00001F); + assertArrayEquals(new float[] {-1, 0, 0}, buffer.vertices.get(4).normal, 0.00001F); + assertArrayEquals(new float[] {0.25F, 0.75F}, first.uv, 0F); + for (Vertex vertex : buffer.vertices) { + assertEquals(0x123456, vertex.light); + assertEquals(0x789abc, vertex.overlay); + assertArrayEquals(new int[] {255, 255, 255, 255}, vertex.color); + } + assertNormals(buffer); + } + + @Test public void drillRetainsSixDirectionsSixteenVerticesAndLegacyUvs() throws Exception { + ElectricDrillTileEntity drill = new ElectricDrillTileEntity(); + set(ElectricDrillTileEntity.class, drill, "laserLength", 5); + LaserDrillRenderer renderer = new LaserDrillRenderer(null); + for (Direction direction : Direction.values()) { + set(ElectricDrillTileEntity.class, drill, "facingCache", direction); + MatrixStack matrices = new MatrixStack(); + matrices.translate(11, -5, 7); + MatrixStack.Entry before = matrices.getLast(); + Matrix4f matrix = before.getMatrix().copy(); + RecordingBuffer buffer = new RecordingBuffer(); + renderer.render(drill, 0.5F, matrices, buffer, 0, 17); + assertSame(before, matrices.getLast()); + assertEquals(matrix, matrices.getLast().getMatrix()); + assertTrue(matrices.clear()); + assertEquals(direction.toString(), 16, buffer.vertices.size()); + assertArrayEquals(new float[] {11.5F, -4.5F, 7.5F}, + midpoint(buffer.vertices.get(0), buffer.vertices.get(3)), 0.00001F); + assertArrayEquals(new float[] {11.5F + direction.getXOffset() * 5, + -4.5F + direction.getYOffset() * 5, 7.5F + direction.getZOffset() * 5}, + midpoint(buffer.vertices.get(1), buffer.vertices.get(2)), 0.00001F); + for (Vertex vertex : buffer.vertices) { + assertEquals(FULL_BRIGHT, vertex.light); + assertEquals(17, vertex.overlay); + assertArrayEquals(new float[] {0, 1}, vertex.uv, 0F); + } + assertNormals(buffer); + } + } + + @Test public void idleDrillDoesNotTouchTheStackOrEmitVertices() { + MatrixStack matrices = new MatrixStack(); + MatrixStack.Entry before = matrices.getLast(); + RecordingBuffer buffer = new RecordingBuffer(); + new LaserDrillRenderer(null).render(new ElectricDrillTileEntity(), 0, matrices, buffer, 0, 0); + assertSame(before, matrices.getLast()); + assertTrue(matrices.clear()); + assertTrue(buffer.vertices.isEmpty()); + } + + @Test public void turretRetainsBarrelUvsBeamTimingFullBrightAndStackBalance() throws Exception { + LaserTurretTileEntity turret = turret(); + LaserTurretRenderer renderer = new LaserTurretRenderer(null); + turret.laserBlastLength = 5; + turret.targetLocked = true; + turret.rotOldYaw = turret.rotYaw = -90; + for (int charge : new int[] {0, 1, 10, 11}) { + set(LaserTurretTileEntity.class, turret, "laserAttack", charge); + MatrixStack matrices = new MatrixStack(); + MatrixStack.Entry before = matrices.getLast(); + Matrix4f matrix = before.getMatrix().copy(); + RecordingBuffer buffer = new RecordingBuffer(); + renderer.render(turret, 0.5F, matrices, buffer, 0x340012, 23); + boolean beam = charge == 1 || charge == 10; + assertEquals(beam ? 40 : 24, buffer.vertices.size()); + assertSame(before, matrices.getLast()); + assertEquals(matrix, before.getMatrix()); + assertTrue(matrices.clear()); + assertArrayEquals(new float[] {0.5F, 0.5F}, buffer.vertices.get(0).uv, 0F); + assertArrayEquals(new float[] {1, 1}, buffer.vertices.get(2).uv, 0F); + for (int i = 0; i < buffer.vertices.size(); i++) { + assertEquals(i < 24 ? 0x340012 : FULL_BRIGHT, buffer.vertices.get(i).light); + assertEquals(23, buffer.vertices.get(i).overlay); + } + if (beam) { + assertArrayEquals(new float[] {0.5F, 0.75F, 0.5F}, + midpoint(buffer.vertices.get(24), buffer.vertices.get(27)), 0.00001F); + assertArrayEquals(new float[] {0.5F, 0.75F, -4.5F}, + midpoint(buffer.vertices.get(25), buffer.vertices.get(26)), 0.00001F); + assertArrayEquals(new float[] {0, 1}, buffer.vertices.get(24).uv, 0F); + assertArrayEquals(new float[] {0.5F, 0.5F}, buffer.vertices.get(26).uv, 0F); + } + assertNormals(buffer); + } + turret.setEnergy(1500, Power.ELECTRIC_POWER); + RecordingBuffer active = new RecordingBuffer(); + renderer.render(turret, 0, new MatrixStack(), active, 0, 0); + assertArrayEquals(new float[] {0.5F, 0}, active.vertices.get(0).uv, 0F); + assertArrayEquals(new float[] {1, 0.5F}, active.vertices.get(2).uv, 0F); + } + + private static void quad(BufferedQuads quads, boolean reverse) { + quads.pos(0, 0, 0).tex(0.25F, 0.75F).endVertex(); + quads.pos(reverse ? 0 : 1, reverse ? 1 : 0, 0).tex(0.5F, 0.75F).endVertex(); + quads.pos(1, 1, 0).tex(0.5F, 1).endVertex(); + quads.pos(reverse ? 1 : 0, reverse ? 0 : 1, 0).tex(0.25F, 1).endVertex(); + } + + private static float[] midpoint(Vertex a, Vertex b) { + return new float[] {(a.position[0] + b.position[0]) / 2, + (a.position[1] + b.position[1]) / 2, (a.position[2] + b.position[2]) / 2}; + } + + private static void assertNormals(RecordingBuffer buffer) { + for (Vertex vertex : buffer.vertices) { + float[] n = vertex.normal; + assertEquals(1F, n[0] * n[0] + n[1] * n[1] + n[2] * n[2], 0.00001F); + } + } + + // Keep the real turret controls; only omit the world-dependent constructor. + private static LaserTurretTileEntity turret() throws Exception { + Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + LaserTurretTileEntity turret = (LaserTurretTileEntity) + ((Unsafe) unsafeField.get(null)).allocateInstance(LaserTurretTileEntity.class); + set(TileEntitySimplePowerMachine.class, turret, "types", new ConduitType[] {Power.ELECTRIC_POWER}); + set(TileEntitySimplePowerMachine.class, turret, "energyBuffers", new float[] {0}); + set(TileEntitySimplePowerMachine.class, turret, "energyBufferSizes", new float[] {2000}); + return turret; + } + + private static void set(Class owner, Object target, String name, Object value) throws Exception { + Field field = owner.getDeclaredField(name); + field.setAccessible(true); + field.set(target, value); + } + + private static final class Vertex { + float[] position; + float[] uv; + float[] normal; + int[] color; + int light; + int overlay; + } + + private static final class RecordingBuffer implements IVertexBuilder, IRenderTypeBuffer { + final List vertices = new ArrayList<>(); + Vertex vertex = new Vertex(); + @Override public IVertexBuilder getBuffer(RenderType type) { return this; } + @Override public IVertexBuilder pos(double x, double y, double z) { vertex.position = new float[] {(float) x, (float) y, (float) z}; return this; } + @Override public IVertexBuilder color(int r, int g, int b, int a) { vertex.color = new int[] {r, g, b, a}; return this; } + @Override public IVertexBuilder tex(float u, float v) { vertex.uv = new float[] {u, v}; return this; } + @Override public IVertexBuilder overlay(int u, int v) { vertex.overlay = u | v << 16; return this; } + @Override public IVertexBuilder lightmap(int u, int v) { vertex.light = u | v << 16; return this; } + @Override public IVertexBuilder normal(float x, float y, float z) { vertex.normal = new float[] {x, y, z}; return this; } + @Override public void endVertex() { vertices.add(vertex); vertex = new Vertex(); } + } +} diff --git a/src/test/java/zone/moddev/mc/electricadvantage/init/VillagesTest.java b/src/test/java/zone/moddev/mc/electricadvantage/init/VillagesTest.java index 396e834..3ce2b76 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/init/VillagesTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/init/VillagesTest.java @@ -33,7 +33,7 @@ private static void assertOffer(int minimum, int maximum, boolean upper, int eme }; MerchantOffer offer = Villages.sell(net.minecraft.item.Items.APPLE, minimum, maximum) .getOffer(null, random); - CompoundNBT nbt = offer.func_222208_r(); + CompoundNBT nbt = offer.write(); assertEquals("minecraft:emerald", nbt.getCompound("buy").getString("id")); assertEquals(emeralds, nbt.getCompound("buy").getByte("Count")); assertEquals("minecraft:apple", nbt.getCompound("sell").getString("id")); diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java new file mode 100644 index 0000000..165e744 --- /dev/null +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java @@ -0,0 +1,41 @@ +package zone.moddev.mc.electricadvantage.resources; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.junit.Test; +import static org.junit.Assert.*; + +public class BuildWorkflowContractTest { + @Test public void hostedBuildsProvisionAllThreePinnedToolchainsBeforeGradle() throws Exception { + for (String workflow : new String[] {"ci.yml", "codeql-analysis.yml"}) { + String source = new String(Files.readAllBytes(Paths.get(".github/workflows", workflow)), StandardCharsets.UTF_8); + int setup = source.indexOf("- name: Set up Gradle"); + for (String version : new String[] {"25.0.3+9.0.LTS", "8.0.502+7", "17.0.1+12"}) { + int pin = source.indexOf("java-version: '" + version + "'"); + assertTrue(workflow + " missing pinned JDK " + version, pin >= 0 && pin < setup); + } + assertTrue(source.contains("installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64")); + assertTrue(source.contains("installations.auto-detect=false")); + assertTrue(source.contains("installations.auto-download=false")); + assertTrue(source.indexOf("- name: Use pinned build toolchains") < setup); + assertFalse(source.contains("distribution: microsoft")); + } + } + + @Test public void dependencyPolicyPrecedesEveryPinnedCheckout() throws Exception { + for (String workflow : new String[] {"ci.yml", "codeql-analysis.yml"}) { + String source = new String(Files.readAllBytes(Paths.get(".github/workflows", workflow)), StandardCharsets.UTF_8); + int policy = source.indexOf("git config --global core.autocrlf false"); + assertTrue(policy > 0); + assertTrue(policy < source.indexOf("repository: MinecraftModDevelopmentMods/OreSpawn")); + assertTrue(policy < source.indexOf("repository: MinecraftModDevelopmentMods/BaseMetals")); + assertTrue(policy < source.indexOf("repository: MinecraftModDevelopmentMods/PowerAdvantage")); + assertTrue(source.contains("ref: 5613baf876747ed071cb7ad7e2aff4e0ce4f0a03")); + assertTrue(source.contains("ref: 1d166d917663d4b4a5a88a86440adc0ae761e393")); + assertTrue(source.contains("ref: b15e2091e9647860bd90284aef6135a311692864")); + assertTrue(source.contains("branches: [master-1.15.2")); + assertFalse(source.contains("master-1.14.4")); + } + } +} From 3c5de8c7ba895b91428d839b873d5ec5d00889f2 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 11:44:47 +0000 Subject: [PATCH 2/8] Validate the native 1.15 resource pack format --- build.gradle | 3 +++ src/main/resources/pack.mcmeta | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3dbbfa1..a0d9bf4 100644 --- a/build.gradle +++ b/build.gradle @@ -341,6 +341,9 @@ tasks.register('verifyReleaseConfiguration') { group = 'verification' description = 'Validates release identity, target metadata, and dependency policy.' doLast { + if (new JsonSlurper().parse(file('src/main/resources/pack.mcmeta')).pack.pack_format != 5) { + throw new GradleException('Minecraft 1.15.2 resources must use pack format 5') + } if (project.mod_version != '2.2.7.115021') { throw new GradleException("Unexpected ElectricAdvantage release version: ${project.mod_version}") } diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 146a2e4..e779902 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack":{ - "pack_format":4, + "pack_format":5, "description":"Electric Advantage" } } From a73d1adb1f2e9be3bc032df8222ae34d8c1b2b99 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 11:49:28 +0000 Subject: [PATCH 3/8] Check resource metadata against the 1.15 target --- .../mc/electricadvantage/resources/BlockLootResourceTest.java | 4 ++-- .../mc/electricadvantage/resources/RecipeResourceTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/BlockLootResourceTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/BlockLootResourceTest.java index 367f230..85d9eba 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/resources/BlockLootResourceTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/BlockLootResourceTest.java @@ -33,8 +33,8 @@ public class BlockLootResourceTest { assertFalse(Files.exists(root.resolve("pump_pipe_electric.json"))); } - @Test public void resourcePackDeclaresTheNativeOneFourteenFormat() throws Exception { - assertEquals(4, read(Paths.get("src/main/resources/pack.mcmeta")) + @Test public void resourcePackDeclaresTheNativeOneFifteenFormat() throws Exception { + assertEquals(5, read(Paths.get("src/main/resources/pack.mcmeta")) .getAsJsonObject("pack").get("pack_format").getAsInt()); } diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeResourceTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeResourceTest.java index 34c012f..e8ce5cc 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeResourceTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeResourceTest.java @@ -18,7 +18,7 @@ import org.junit.Test; public class RecipeResourceTest { - @Test public void allRecipesUseTheNativeOneFourteenDataPackLocationAndSerializers() throws IOException { + @Test public void allRecipesUseTheNativeOneFifteenDataPackLocationAndSerializers() throws IOException { Path recipes = Paths.get("src/main/resources/data/electricadvantage/recipes"); List files; try (Stream stream = Files.list(recipes)) { From 2165f3abc1eda12b2f5f3699cbf52677a7b6fe64 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 12:33:52 +0000 Subject: [PATCH 4/8] Use pinned JDKs in every hosted Gradle build --- .github/workflows/ci.yml | 15 ++++++++------- .github/workflows/codeql-analysis.yml | 15 ++++++++------- .../resources/BuildWorkflowContractTest.java | 12 +++++++++--- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63b6d5a..4c9686c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,11 +58,12 @@ jobs: distribution: temurin java-version: '17.0.1+12' - name: Use pinned build toolchains + # These are Gradle project properties, not JVM system properties. shell: bash run: >- - echo "GRADLE_OPTS=-Dorg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64 - -Dorg.gradle.java.installations.auto-detect=false - -Dorg.gradle.java.installations.auto-download=false" >> "$GITHUB_ENV" + echo "MMD_GRADLE_TOOLCHAINS=-Porg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64 + -Porg.gradle.java.installations.auto-detect=false + -Porg.gradle.java.installations.auto-download=false" >> "$GITHUB_ENV" - name: Set up Gradle uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6 - name: Build 1.15.2 dependency chain @@ -74,11 +75,11 @@ jobs: basemetals="$GITHUB_WORKSPACE/.ci-dependencies/BaseMetals" power="$GITHUB_WORKSPACE/.ci-dependencies/PowerAdvantage" chmod +x "$orespawn/gradlew" "$basemetals/gradlew" "$power/gradlew" - (cd "$orespawn" && ./gradlew jar --no-daemon --stacktrace) - (cd "$basemetals" && ./gradlew jar --no-daemon --stacktrace) + (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.1.115021-deobf.jar" bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.115021-deobf.jar" - (cd "$power" && ./gradlew jar verifyReleaseDependencies \ + (cd "$power" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar verifyReleaseDependencies \ -PbaseMetalsDeobfJar="$bmjar" -PoreSpawnDeobfJar="$osjar" \ --no-daemon --stacktrace) powerjar="$power/build/libs-dev/PowerAdvantage-2.4.6.115021-deobf.jar" @@ -89,7 +90,7 @@ jobs: echo "power_ref=$(git -C "$power" rev-parse HEAD)" >> "$GITHUB_OUTPUT" - name: Build and audit release artifacts run: >- - ./gradlew clean check build javadoc verifyReleaseDependencies verifyReleaseArtifacts + ./gradlew $MMD_GRADLE_TOOLCHAINS clean check build javadoc verifyReleaseDependencies verifyReleaseArtifacts writeReleaseChecksums verifyEclipseProductionClasspath -PpowerAdvantageDeobfJar=${{ steps.dependencies.outputs.power }} -Ppoweradvantage_source_ref=${{ steps.dependencies.outputs.power_ref }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d01e921..7c433ba 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,11 +58,12 @@ jobs: distribution: temurin java-version: '17.0.1+12' - name: Use pinned build toolchains + # These are Gradle project properties, not JVM system properties. shell: bash run: >- - echo "GRADLE_OPTS=-Dorg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64 - -Dorg.gradle.java.installations.auto-detect=false - -Dorg.gradle.java.installations.auto-download=false" >> "$GITHUB_ENV" + echo "MMD_GRADLE_TOOLCHAINS=-Porg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64 + -Porg.gradle.java.installations.auto-detect=false + -Porg.gradle.java.installations.auto-download=false" >> "$GITHUB_ENV" - name: Set up Gradle uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6 - name: Build 1.15.2 dependency chain @@ -74,11 +75,11 @@ jobs: basemetals="$GITHUB_WORKSPACE/.ci-dependencies/BaseMetals" power="$GITHUB_WORKSPACE/.ci-dependencies/PowerAdvantage" chmod +x "$orespawn/gradlew" "$basemetals/gradlew" "$power/gradlew" - (cd "$orespawn" && ./gradlew jar --no-daemon --stacktrace) - (cd "$basemetals" && ./gradlew jar --no-daemon --stacktrace) + (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.1.115021-deobf.jar" bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.115021-deobf.jar" - (cd "$power" && ./gradlew jar verifyReleaseDependencies \ + (cd "$power" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar verifyReleaseDependencies \ -PbaseMetalsDeobfJar="$bmjar" -PoreSpawnDeobfJar="$osjar" \ --no-daemon --stacktrace) powerjar="$power/build/libs-dev/PowerAdvantage-2.4.6.115021-deobf.jar" @@ -94,7 +95,7 @@ jobs: - name: Compile ElectricAdvantage production code run: | chmod +x ./gradlew - ./gradlew clean classes --rerun-tasks --no-build-cache --no-daemon --stacktrace \ + ./gradlew $MMD_GRADLE_TOOLCHAINS clean classes --rerun-tasks --no-build-cache --no-daemon --stacktrace \ -PpowerAdvantageDeobfJar=${{ steps.dependencies.outputs.power }} \ -Ppoweradvantage_source_ref=${{ steps.dependencies.outputs.power_ref }} \ -PbaseMetalsDeobfJar=${{ steps.dependencies.outputs.basemetals }} \ diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java index 165e744..a4e82dd 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java @@ -15,9 +15,15 @@ public class BuildWorkflowContractTest { int pin = source.indexOf("java-version: '" + version + "'"); assertTrue(workflow + " missing pinned JDK " + version, pin >= 0 && pin < setup); } - assertTrue(source.contains("installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64")); - assertTrue(source.contains("installations.auto-detect=false")); - assertTrue(source.contains("installations.auto-download=false")); + assertTrue(source.contains("-Porg.gradle.java.installations.paths=$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64")); + assertTrue(source.contains("-Porg.gradle.java.installations.auto-detect=false")); + assertTrue(source.contains("-Porg.gradle.java.installations.auto-download=false")); + assertFalse(source.contains("-Dorg.gradle.java.installations.")); + for (String line : source.split("\\R")) { + if (line.contains("./gradlew ") && !line.contains("chmod")) { + assertTrue(workflow + ": " + line, line.contains("./gradlew $MMD_GRADLE_TOOLCHAINS ")); + } + } assertTrue(source.indexOf("- name: Use pinned build toolchains") < setup); assertFalse(source.contains("distribution: microsoft")); } From f39a7f8f2f09727cd8dec1a1ebc553d52d710404 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 12:58:51 +0000 Subject: [PATCH 5/8] Register recipe conditions after parallel mod setup --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- CHANGELOG.txt | 1 + README.md | 2 +- build.gradle | 4 +- gradle.properties | 4 +- .../electricadvantage/ElectricAdvantage.java | 3 +- .../resources/BuildWorkflowContractTest.java | 2 +- .../RecipeRegistrationThreadTest.java | 49 +++++++++++++++++++ 9 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeRegistrationThreadTest.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c9686c..607ebf2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - ref: b15e2091e9647860bd90284aef6135a311692864 + ref: 75d24d2641e8123ff7a7f961d9a1e5a1d5203194 path: .ci-dependencies/PowerAdvantage - name: Install pinned Java 25 Mavenizer runtime uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7c433ba..67156ec 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -40,7 +40,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - ref: b15e2091e9647860bd90284aef6135a311692864 + ref: 75d24d2641e8123ff7a7f961d9a1e5a1d5203194 path: .ci-dependencies/PowerAdvantage - name: Install pinned Java 25 Mavenizer runtime uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 0583268..584ed5f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -72,3 +72,4 @@ Electric Advantage 2.2.1.112021 - Keep Base Metals integration reflection-based while retaining its distribution dependency. - Preserve vertical Electric Drill orientation when chunks and worlds reload. - Preserve Electric Advantage registry, tile entity, entity, asset, configuration, and saved-world identities. +- Register recipe conditions after parallel setup to prevent intermittent missing recipes at startup. diff --git a/README.md b/README.md index 8410a4b..9919188 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Build the matching 1.15 PowerAdvantage, Base Metals and OreSpawn deobf jars firs Dependency versions, checksums and the exact Power source reference belong in `gradle.properties`. Release audits reject missing or placeholder pins; do not bypass those checks or substitute another target's dependencies. Power Advantage -`2.4.6.115021` is pinned to source `b15e2091e9647860bd90284aef6135a311692864`. +`2.4.6.115021` is pinned to source `75d24d2641e8123ff7a7f961d9a1e5a1d5203194`. Base Metals `3.0.1.115021` and OreSpawn `4.1.1.115021` also have exact source and SHA-256 pins. With the standard sibling layout: diff --git a/build.gradle b/build.gradle index a0d9bf4..beb3d51 100644 --- a/build.gradle +++ b/build.gradle @@ -374,8 +374,8 @@ tasks.register('verifyReleaseConfiguration') { } if (project.poweradvantage_version != '2.4.6.115021' || project.poweradvantage_source_repository != 'MinecraftModDevelopmentMods/PowerAdvantage' - || project.poweradvantage_source_ref != 'b15e2091e9647860bd90284aef6135a311692864' - || project.poweradvantage_deobf_sha256 != '2C3ADBCA79859DFA2C14EF8DC9068BF9F202D72FDB1D37B51ED4DE1B5B7E866A') { + || project.poweradvantage_source_ref != '75d24d2641e8123ff7a7f961d9a1e5a1d5203194' + || project.poweradvantage_deobf_sha256 != 'F5029356CB837E7D782BA59D4C3B961CE0AAA116B739F14DA63F0A13562A2D1F') { throw new GradleException('Unexpected PowerAdvantage compile dependency identity') } if (project.basemetals_version != '3.0.1.115021' diff --git a/gradle.properties b/gradle.properties index 0bceb64..ccf860b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,8 +38,8 @@ cf_versions=1.15.2 poweradvantage_version=2.4.6.115021 poweradvantage_source_repository=MinecraftModDevelopmentMods/PowerAdvantage # Exact Power Advantage source and development jar used by local and CI builds. -poweradvantage_source_ref=b15e2091e9647860bd90284aef6135a311692864 -poweradvantage_deobf_sha256=2C3ADBCA79859DFA2C14EF8DC9068BF9F202D72FDB1D37B51ED4DE1B5B7E866A +poweradvantage_source_ref=75d24d2641e8123ff7a7f961d9a1e5a1d5203194 +poweradvantage_deobf_sha256=F5029356CB837E7D782BA59D4C3B961CE0AAA116B739F14DA63F0A13562A2D1F basemetals_version=3.0.1.115021 basemetals_source_commit=1d166d917663d4b4a5a88a86440adc0ae761e393 diff --git a/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java b/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java index 0948129..63d24ef 100644 --- a/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java +++ b/src/main/java/zone/moddev/mc/electricadvantage/ElectricAdvantage.java @@ -52,7 +52,6 @@ public ElectricAdvantage() { Entities.init(); Enchantments.init(); GUI.init(); - RecipeConditions.register(); ElectricLegacyMigrations.register(); migrateLegacyOreSpawnConfiguration(); @@ -96,6 +95,8 @@ private static void migrateLegacyConfiguration() { } private void commonSetup(FMLCommonSetupEvent event) { + // CraftingHelper's shared condition map is not safe during parallel loading. + net.minecraftforge.fml.DeferredWorkQueue.runLater(RecipeConditions::register); ElectricAdvantageConfig.apply(); Recipes.init(); TreasureChests.init(FMLPaths.CONFIGDIR.get()); diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java index a4e82dd..58d01f6 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java @@ -39,7 +39,7 @@ public class BuildWorkflowContractTest { assertTrue(policy < source.indexOf("repository: MinecraftModDevelopmentMods/PowerAdvantage")); assertTrue(source.contains("ref: 5613baf876747ed071cb7ad7e2aff4e0ce4f0a03")); assertTrue(source.contains("ref: 1d166d917663d4b4a5a88a86440adc0ae761e393")); - assertTrue(source.contains("ref: b15e2091e9647860bd90284aef6135a311692864")); + assertTrue(source.contains("ref: 75d24d2641e8123ff7a7f961d9a1e5a1d5203194")); assertTrue(source.contains("branches: [master-1.15.2")); assertFalse(source.contains("master-1.14.4")); } diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeRegistrationThreadTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeRegistrationThreadTest.java new file mode 100644 index 0000000..296975d --- /dev/null +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/RecipeRegistrationThreadTest.java @@ -0,0 +1,49 @@ +package zone.moddev.mc.electricadvantage.resources; + +import java.io.InputStream; +import org.junit.Test; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Handle; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import static org.junit.Assert.*; + +public class RecipeRegistrationThreadTest { + @Test public void sharedForgeConditionsAreRegisteredAfterParallelSetup() throws Exception { + ClassNode node = new ClassNode(); + try (InputStream input = getClass().getResourceAsStream("/zone/moddev/mc/electricadvantage/ElectricAdvantage.class")) { + assertNotNull(input); + new ClassReader(input).accept(node, 0); + } + String conditions = "zone/moddev/mc/electricadvantage/recipe/RecipeConditions"; + int queued = 0; + for (MethodNode method : node.methods) { + boolean registrationRunnable = false; + for (AbstractInsnNode instruction : method.instructions.toArray()) { + if (instruction instanceof MethodInsnNode) { + MethodInsnNode call = (MethodInsnNode) instruction; + assertFalse("Forge's condition HashMap is not safe during parallel loading", + call.owner.equals(conditions) && call.name.equals("register")); + if (call.owner.equals("net/minecraftforge/fml/DeferredWorkQueue") + && call.name.equals("runLater") && registrationRunnable) { + assertEquals("Register conditions during common setup", "commonSetup", method.name); + queued++; + registrationRunnable = false; + } + } + if (instruction instanceof InvokeDynamicInsnNode) { + for (Object argument : ((InvokeDynamicInsnNode) instruction).bsmArgs) { + if (argument instanceof Handle && ((Handle) argument).getOwner().equals(conditions) + && ((Handle) argument).getName().equals("register")) { + registrationRunnable = true; + } + } + } + } + } + assertEquals("Queue registration exactly once on Forge's loading thread", 1, queued); + } +} From 58bb1a78d7a218779cf92a866db575f72a577546 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 14:30:20 +0000 Subject: [PATCH 6/8] Pin Base Metals 3.0.2 and matching local Power source Dependency sources are local-only. Publish the exact Base Metals and Power commits upstream before PR or hosted builds. --- .github/workflows/ci.yml | 8 +++++--- .github/workflows/codeql-analysis.yml | 8 +++++--- build.gradle | 10 +++++----- gradle.properties | 8 ++++---- .../resources/BuildWorkflowContractTest.java | 7 +++++-- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 607ebf2..f7d0f9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,13 +34,15 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/BaseMetals - ref: 1d166d917663d4b4a5a88a86440adc0ae761e393 + # Local-only Base Metals source; publish upstream before PR/hosted builds. + ref: ac1781e7cade15045ffe0135077087b4d1722603 path: .ci-dependencies/BaseMetals - name: Check out PowerAdvantage 1.15.2 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - ref: 75d24d2641e8123ff7a7f961d9a1e5a1d5203194 + # Local-only Power source; publish upstream before PR/hosted builds. + ref: 6666099a734eba16561d98c86f3f4bb1b7c742f7 path: .ci-dependencies/PowerAdvantage - name: Install pinned Java 25 Mavenizer runtime uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 @@ -78,7 +80,7 @@ jobs: (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.1.115021-deobf.jar" - bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.115021-deobf.jar" + bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.2.115021-deobf.jar" (cd "$power" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar verifyReleaseDependencies \ -PbaseMetalsDeobfJar="$bmjar" -PoreSpawnDeobfJar="$osjar" \ --no-daemon --stacktrace) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 67156ec..c15fe44 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,13 +34,15 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/BaseMetals - ref: 1d166d917663d4b4a5a88a86440adc0ae761e393 + # Local-only Base Metals source; publish upstream before PR/hosted builds. + ref: ac1781e7cade15045ffe0135077087b4d1722603 path: .ci-dependencies/BaseMetals - name: Check out PowerAdvantage 1.15.2 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - ref: 75d24d2641e8123ff7a7f961d9a1e5a1d5203194 + # Local-only Power source; publish upstream before PR/hosted builds. + ref: 6666099a734eba16561d98c86f3f4bb1b7c742f7 path: .ci-dependencies/PowerAdvantage - name: Install pinned Java 25 Mavenizer runtime uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 @@ -78,7 +80,7 @@ jobs: (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.1.115021-deobf.jar" - bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.1.115021-deobf.jar" + bmjar="$basemetals/build/libs-dev/BaseMetals-3.0.2.115021-deobf.jar" (cd "$power" && ./gradlew $MMD_GRADLE_TOOLCHAINS jar verifyReleaseDependencies \ -PbaseMetalsDeobfJar="$bmjar" -PoreSpawnDeobfJar="$osjar" \ --no-daemon --stacktrace) diff --git a/build.gradle b/build.gradle index beb3d51..a0e8bd2 100644 --- a/build.gradle +++ b/build.gradle @@ -179,7 +179,7 @@ if (!powerAdvantageDeobfJar.isFile()) { // here so another developer can override them without editing the script. def baseMetalsDeobfJar = file(providers.gradleProperty('baseMetalsDeobfJar') .getOrElse('../../../../BaseMetals/BaseMetals 115/BaseMetals/build/libs-dev/' - + 'BaseMetals-3.0.1.115021-deobf.jar')) + + 'BaseMetals-3.0.2.115021-deobf.jar')) if (!baseMetalsDeobfJar.isFile()) { throw new GradleException("Missing Base Metals deobf jar at ${baseMetalsDeobfJar}. " + "Build Base Metals 1.15 first, or pass -PbaseMetalsDeobfJar=.") @@ -374,15 +374,15 @@ tasks.register('verifyReleaseConfiguration') { } if (project.poweradvantage_version != '2.4.6.115021' || project.poweradvantage_source_repository != 'MinecraftModDevelopmentMods/PowerAdvantage' - || project.poweradvantage_source_ref != '75d24d2641e8123ff7a7f961d9a1e5a1d5203194' + || project.poweradvantage_source_ref != '6666099a734eba16561d98c86f3f4bb1b7c742f7' || project.poweradvantage_deobf_sha256 != 'F5029356CB837E7D782BA59D4C3B961CE0AAA116B739F14DA63F0A13562A2D1F') { throw new GradleException('Unexpected PowerAdvantage compile dependency identity') } - if (project.basemetals_version != '3.0.1.115021' + if (project.basemetals_version != '3.0.2.115021' || project.orespawn_version != '4.1.1.115021' - || project.basemetals_source_commit != '1d166d917663d4b4a5a88a86440adc0ae761e393' + || project.basemetals_source_commit != 'ac1781e7cade15045ffe0135077087b4d1722603' || project.orespawn_source_commit != '5613baf876747ed071cb7ad7e2aff4e0ce4f0a03' - || project.basemetals_deobf_sha256 != 'A98EAC370D908F14103DB6D064C738160161FDD7203F30905562B23EEE265210' + || project.basemetals_deobf_sha256 != '426FE639C97E1DE4F6624957E3CBDE68A5FB7D415A1047903A29DCB35FD9ADA2' || project.orespawn_deobf_sha256 != '358B13375A4B60622C491D6729290971A446FF14D524A600CA13710934DB3FDC' || project.forge_installer_sha256 != '84FD49A743978421B26F62AC78222289FE892A46F996CF11CB5E05B7441A7773') { throw new GradleException('Unexpected native dependency pins') diff --git a/gradle.properties b/gradle.properties index ccf860b..cb642bb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,12 +38,12 @@ cf_versions=1.15.2 poweradvantage_version=2.4.6.115021 poweradvantage_source_repository=MinecraftModDevelopmentMods/PowerAdvantage # Exact Power Advantage source and development jar used by local and CI builds. -poweradvantage_source_ref=75d24d2641e8123ff7a7f961d9a1e5a1d5203194 +poweradvantage_source_ref=6666099a734eba16561d98c86f3f4bb1b7c742f7 poweradvantage_deobf_sha256=F5029356CB837E7D782BA59D4C3B961CE0AAA116B739F14DA63F0A13562A2D1F -basemetals_version=3.0.1.115021 -basemetals_source_commit=1d166d917663d4b4a5a88a86440adc0ae761e393 -basemetals_deobf_sha256=A98EAC370D908F14103DB6D064C738160161FDD7203F30905562B23EEE265210 +basemetals_version=3.0.2.115021 +basemetals_source_commit=ac1781e7cade15045ffe0135077087b4d1722603 +basemetals_deobf_sha256=426FE639C97E1DE4F6624957E3CBDE68A5FB7D415A1047903A29DCB35FD9ADA2 orespawn_version=4.1.1.115021 orespawn_source_commit=5613baf876747ed071cb7ad7e2aff4e0ce4f0a03 diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java index 58d01f6..f0d44bd 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java @@ -38,8 +38,11 @@ public class BuildWorkflowContractTest { assertTrue(policy < source.indexOf("repository: MinecraftModDevelopmentMods/BaseMetals")); assertTrue(policy < source.indexOf("repository: MinecraftModDevelopmentMods/PowerAdvantage")); assertTrue(source.contains("ref: 5613baf876747ed071cb7ad7e2aff4e0ce4f0a03")); - assertTrue(source.contains("ref: 1d166d917663d4b4a5a88a86440adc0ae761e393")); - assertTrue(source.contains("ref: 75d24d2641e8123ff7a7f961d9a1e5a1d5203194")); + assertTrue(source.contains("ref: ac1781e7cade15045ffe0135077087b4d1722603")); + assertTrue(source.contains("BaseMetals-3.0.2.115021-deobf.jar")); + assertTrue(source.contains("Local-only Base Metals source; publish upstream before PR/hosted builds.")); + assertTrue(source.contains("ref: 6666099a734eba16561d98c86f3f4bb1b7c742f7")); + assertTrue(source.contains("Local-only Power source; publish upstream before PR/hosted builds.")); assertTrue(source.contains("branches: [master-1.15.2")); assertFalse(source.contains("master-1.14.4")); } From a4e765579ec9f595509091e928c17a736acccc05 Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Mon, 26 Oct 2026 14:55:06 +0000 Subject: [PATCH 7/8] Clarify local 1.15 validation and unpublished dependency pins --- CHANGELOG.txt | 7 +++---- README.md | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 584ed5f..bedab15 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,7 +2,7 @@ Electric Advantage 2.2.7.115021 (local port candidate) - Target Minecraft 1.15.2, Forge 31.2.57 and snapshot 20200514-1.15.1/MCP 20200515.085601. - Retain ForgeGradle 7.0.34, Gradle 9.6.1, Renamer 1.1.5 and Java 8 production bytecode. -- Pin native Power Advantage 2.4.6.115021, Base Metals 3.0.1.115021 and OreSpawn 4.1.1.115021 source/development artifacts. +- Pin native Power Advantage 2.4.6.115021, Base Metals 3.0.2.115021 and OreSpawn 4.1.1.115021 source/development artifacts. - Provision pinned Java 25 Mavenizer, Java 8 production and Java 17 Gradle toolchains in CI and CodeQL. - Use native MatrixStack/buffered entity and tile renderers, retaining the legacy vertex streams, UVs and beam orientation/full-bright behavior. - Move the electric track's cutout layer to client setup and use Power's native-properties constructor, retaining shared conduit inheritance, states, events and connectivity without duplicated callbacks. @@ -10,9 +10,8 @@ Electric Advantage 2.2.7.115021 (local port candidate) - Use the native short-NBT factory and renamed skylight predicate without changing saved values or solar-output arithmetic. - Preserve registries, migration aliases, entity/tile IDs, fluids, NBT, ore mining levels, loot, recipes and discoveries; no balance changes. - Add focused buffered-renderer geometry, UV, normals, light, control and matrix-stack regression tests. -- Native production/test compilation, all 44 unit tests, full release/dependency/artifact audits and Eclipse verification pass, with no skipped tests; actual ECJ reports zero errors (51 warnings). -- Resolve the preserved solar-panel solidness regression against pinned Power source b15e2091e9647860bd90284aef6135a311692864; retain the original assertion and add shared scaffold inheritance and non-solid drill/turret contracts. -- Packaged startup, combined runtime, graphical/manual acceptance and disposable-copy migration remain pending; not published. +- Preserve solar-panel solidity, shared scaffold inheritance and the non-solid drill/turret properties with focused regression tests. +- Record the exact build, operating, migration and client results in Power Advantage's shared 1.15 test notes; manual acceptance remains separate. Not published. Electric Advantage 2.2.6.114041 diff --git a/README.md b/README.md index 9919188..4fefb46 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,11 @@ # ElectricAdvantage -**Minecraft 1.15.2 port candidate, version 2.2.7.115021.** Local native compilation, -all 44 unit tests, full Gradle release-artifact/dependency audits and Eclipse -verification pass, with no tests skipped. Actual ECJ production compilation reports -zero errors (51 warnings). Tests include solar-panel solidness, non-solid drill and -turrets, shared scaffold properties/network inheritance and buffered renderer contracts. -Packaged startup, combined-mod runtime, graphical acceptance and disposable-copy -world migration remain pending for this target. Historical +**Minecraft 1.15.2 port candidate, version 2.2.7.115021.** See the +[shared test record](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.15.2/docs/1.15/CURRENT-QUALIFICATION.md) +for exact jars, automated machine and upgrade results, and remaining manual +checks. This version is not published. Historical [1.14 test results](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.14.4/docs/1.14/BROADER-QUALIFICATION.md) -are not 1.15 qualification evidence. Nothing has been published. +are not 1.15 qualification evidence. Electric Advantage adds electric machines, generation, storage, automation, and defence to Power Advantage for Minecraft 1.15.2. @@ -26,8 +23,13 @@ Build the matching 1.15 PowerAdvantage, Base Metals and OreSpawn deobf jars firs Dependency versions, checksums and the exact Power source reference belong in `gradle.properties`. Release audits reject missing or placeholder pins; do not bypass those checks or substitute another target's dependencies. Power Advantage -`2.4.6.115021` is pinned to source `75d24d2641e8123ff7a7f961d9a1e5a1d5203194`. -Base Metals `3.0.1.115021` and OreSpawn `4.1.1.115021` also have exact source and SHA-256 pins. +`2.4.6.115021` is pinned to source `6666099a734eba16561d98c86f3f4bb1b7c742f7`. +Base Metals `3.0.2.115021` and OreSpawn `4.1.1.115021` also have exact source and SHA-256 pins. +Base Metals source `ac1781e7cade15045ffe0135077087b4d1722603` and the Power +source pin above are local-only and unpublished. Publish both exact sources +upstream before opening a PR or running hosted builds; hosted reproducibility +and publication readiness are not established. + With the standard sibling layout: ```text From 74fe9e404593c0746f4ec59b31d91fd0c643723a Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Tue, 27 Oct 2026 10:35:41 +0000 Subject: [PATCH 8/8] Record accepted 1.15 visuals and recipe unlocks --- .github/workflows/ci.yml | 2 -- .github/workflows/codeql-analysis.yml | 2 -- CHANGELOG.txt | 4 ++-- README.md | 11 +++++------ .../resources/BuildWorkflowContractTest.java | 2 -- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7d0f9b..c86c599 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,14 +34,12 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/BaseMetals - # Local-only Base Metals source; publish upstream before PR/hosted builds. ref: ac1781e7cade15045ffe0135077087b4d1722603 path: .ci-dependencies/BaseMetals - name: Check out PowerAdvantage 1.15.2 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - # Local-only Power source; publish upstream before PR/hosted builds. ref: 6666099a734eba16561d98c86f3f4bb1b7c742f7 path: .ci-dependencies/PowerAdvantage - name: Install pinned Java 25 Mavenizer runtime diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c15fe44..69df538 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,14 +34,12 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/BaseMetals - # Local-only Base Metals source; publish upstream before PR/hosted builds. ref: ac1781e7cade15045ffe0135077087b4d1722603 path: .ci-dependencies/BaseMetals - name: Check out PowerAdvantage 1.15.2 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/PowerAdvantage - # Local-only Power source; publish upstream before PR/hosted builds. ref: 6666099a734eba16561d98c86f3f4bb1b7c742f7 path: .ci-dependencies/PowerAdvantage - name: Install pinned Java 25 Mavenizer runtime diff --git a/CHANGELOG.txt b/CHANGELOG.txt index bedab15..25e3660 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,4 @@ -Electric Advantage 2.2.7.115021 (local port candidate) +Electric Advantage 2.2.7.115021 - Target Minecraft 1.15.2, Forge 31.2.57 and snapshot 20200514-1.15.1/MCP 20200515.085601. - Retain ForgeGradle 7.0.34, Gradle 9.6.1, Renamer 1.1.5 and Java 8 production bytecode. @@ -11,7 +11,7 @@ Electric Advantage 2.2.7.115021 (local port candidate) - Preserve registries, migration aliases, entity/tile IDs, fluids, NBT, ore mining levels, loot, recipes and discoveries; no balance changes. - Add focused buffered-renderer geometry, UV, normals, light, control and matrix-stack regression tests. - Preserve solar-panel solidity, shared scaffold inheritance and the non-solid drill/turret properties with focused regression tests. -- Record the exact build, operating, migration and client results in Power Advantage's shared 1.15 test notes; manual acceptance remains separate. Not published. +- Record accepted in-game visuals and recipe unlocks alongside the automated machine and migration checks; the shared test notes retain the remaining limits. Electric Advantage 2.2.6.114041 diff --git a/README.md b/README.md index 4fefb46..37fbe72 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # ElectricAdvantage -**Minecraft 1.15.2 port candidate, version 2.2.7.115021.** See the +**Minecraft 1.15.2, version 2.2.7.115021.** See the [shared test record](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.15.2/docs/1.15/CURRENT-QUALIFICATION.md) for exact jars, automated machine and upgrade results, and remaining manual -checks. This version is not published. Historical +checks. Visuals and recipe unlocks were accepted on 27 October 2026. Historical [1.14 test results](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.14.4/docs/1.14/BROADER-QUALIFICATION.md) are not 1.15 qualification evidence. @@ -26,9 +26,8 @@ bypass those checks or substitute another target's dependencies. Power Advantage `2.4.6.115021` is pinned to source `6666099a734eba16561d98c86f3f4bb1b7c742f7`. Base Metals `3.0.2.115021` and OreSpawn `4.1.1.115021` also have exact source and SHA-256 pins. Base Metals source `ac1781e7cade15045ffe0135077087b4d1722603` and the Power -source pin above are local-only and unpublished. Publish both exact sources -upstream before opening a PR or running hosted builds; hosted reproducibility -and publication readiness are not established. +source pin above identify the exact tested dependencies. CI builds them before +Electric Advantage; none is embedded in the Electric Advantage jar. With the standard sibling layout: @@ -73,4 +72,4 @@ runtime or world-upgrade evidence. The implementation namespace is `zone.moddev.mc.electricadvantage`. Runtime identities, registries, tile/entity IDs, NBT, recipes, tags, OreSpawn provider IDs, and assets remain stable. Electric registers its legacy state, tile, and hydroturbine aliases with PowerAdvantage's shared migration hook. The RF- and Tech Reborn-labelled converters belong to Power Advantage and now use Forge Energy. -The historical [1.13 migration guide](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.13.2/docs/1.13/MIGRATION.md) explains the legacy conversion and backup process; migration acceptance for 1.15 remains pending. Always make a whole-world backup before upgrading, keep the complete set of migration backups, and test only disposable copies. Check that every other mod supports the target version; historical results do not qualify this target, unrelated mods or an entire existing modpack. +The historical [1.13 migration guide](https://github.com/MinecraftModDevelopmentMods/PowerAdvantage/blob/master-1.13.2/docs/1.13/MIGRATION.md) explains the legacy conversion and backup process; the shared 1.15 test record lists the completed upgrade routes and their limits. Always make a whole-world backup before upgrading, keep the complete set of migration backups, and test a disposable copy first. Check that every other mod supports the target version; bounded Advantage tests do not qualify unrelated mods or an entire modpack. diff --git a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java index f0d44bd..b04e850 100644 --- a/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/electricadvantage/resources/BuildWorkflowContractTest.java @@ -40,9 +40,7 @@ public class BuildWorkflowContractTest { assertTrue(source.contains("ref: 5613baf876747ed071cb7ad7e2aff4e0ce4f0a03")); assertTrue(source.contains("ref: ac1781e7cade15045ffe0135077087b4d1722603")); assertTrue(source.contains("BaseMetals-3.0.2.115021-deobf.jar")); - assertTrue(source.contains("Local-only Base Metals source; publish upstream before PR/hosted builds.")); assertTrue(source.contains("ref: 6666099a734eba16561d98c86f3f4bb1b7c742f7")); - assertTrue(source.contains("Local-only Power source; publish upstream before PR/hosted builds.")); assertTrue(source.contains("branches: [master-1.15.2")); assertFalse(source.contains("master-1.14.4")); }