diff --git a/.github/scripts/forge47-dependencies.sh b/.github/scripts/forge47-dependencies.sh deleted file mode 100644 index b26aabc..0000000 --- a/.github/scripts/forge47-dependencies.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -cd "${GITHUB_WORKSPACE:?}" - -value() { - sed -n "s/^$1=//p" gradle.properties | tr -d '\r' -} - -fail() { - echo "$*" >&2 - exit 1 -} - -check_hash() { - local file="$1" expected="$2" actual - [[ -f "$file" ]] || fail "Missing pinned input: $file" - read -r actual _ < <(sha256sum < "$file") - [[ "${actual^^}" == "$expected" ]] || fail "SHA-256 mismatch for $file: expected $expected, got ${actual^^}" -} - -[[ "$(value minecraft_version)" == '1.20.1' && "$(value forge_version)" == '47.4.10' ]] || - fail 'This dependency build is only for Minecraft 1.20.1 / Forge 47.4.10' -[[ "$(value poweradvantage_pin_state)" == 'MERGED_SOURCE' ]] || fail 'basePower merged source is not pinned' - -ore_ref="$(value orespawn_source_commit)" -bm_ref="$(value basemetals_source_commit)" -power_ref="$(value poweradvantage_source_ref)" -for ref in "$ore_ref" "$bm_ref" "$power_ref"; do - [[ "$ref" =~ ^[a-f0-9]{40}$ ]] || fail "Invalid dependency source pin: $ref" -done -for key in orespawn_deobf_sha256 orespawn_runtime_sha256 basemetals_deobf_sha256 basemetals_runtime_sha256 \ - poweradvantage_deobf_sha256 poweradvantage_runtime_sha256 poweradvantage_unit_bootstrap_sha256 \ - poweradvantage_unit_bootstrap_jar_sha256 forge_installer_sha256; do - [[ "$(value "$key")" =~ ^[A-F0-9]{64}$ ]] || fail "Invalid dependency checksum: $key" -done - -case "${1:-}" in - pins) - printf 'orespawn_ref=%s\nbasemetals_ref=%s\npower_ref=%s\n' "$ore_ref" "$bm_ref" "$power_ref" >> "$GITHUB_OUTPUT" - exit 0 - ;; - build) ;; - *) fail 'Expected pins or build' ;; -esac - -orespawn="$GITHUB_WORKSPACE/.ci-dependencies/OreSpawn" -basemetals="$GITHUB_WORKSPACE/.ci-dependencies/BaseMetals" -power="$GITHUB_WORKSPACE/.ci-dependencies/PowerAdvantage" -test "$(git -C "$orespawn" rev-parse HEAD)" = "$ore_ref" -test "$(git -C "$basemetals" rev-parse HEAD)" = "$bm_ref" -test "$(git -C "$power" rev-parse HEAD)" = "$power_ref" - -mavenizer="$orespawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar" -check_hash "$mavenizer" '416DCA4797BC55826F0DDCF03FDC405F1990FC15C2133FA27A1F143BF7976177' - -read -r -a toolchains <<< "${MMD_GRADLE_TOOLCHAINS:?}" -ore_version="$(value orespawn_version)" -bm_version="$(value basemetals_version)" -power_version="$(value poweradvantage_version)" -osjar="$orespawn/build/libs-dev/OreSpawn-$ore_version-deobf.jar" -osplayer="$orespawn/build/libs/OreSpawn-$ore_version.jar" -bmjar="$basemetals/build/libs-dev/BaseMetals-$bm_version-deobf.jar" -bmplayer="$basemetals/build/libs/BaseMetals-$bm_version.jar" -powerjar="$power/build/libs-dev/basePower-$power_version-deobf.jar" -powerplayer="$power/build/libs/basePower-$power_version.jar" -bootstrap="$power/test-rig/unit-bootstrap/ForgeCapabilityBootstrap.java" -agent="$power/build/unit-bootstrap/forge-native-unit-bootstrap.jar" -installer="${RUNNER_TEMP:?}/forge-1.20.1-47.4.10-installer.jar" - -(cd "$orespawn" && ./gradlew "${toolchains[@]}" assemble --no-daemon --stacktrace) -check_hash "$osjar" "$(value orespawn_deobf_sha256)" -check_hash "$osplayer" "$(value orespawn_runtime_sha256)" -# The pinned Base Metals build already configures its own verified fixture. -(cd "$basemetals" && ./gradlew "${toolchains[@]}" assemble --no-daemon --stacktrace) -git -C "$basemetals" diff --exit-code HEAD -- -check_hash "$bmjar" "$(value basemetals_deobf_sha256)" -check_hash "$bmplayer" "$(value basemetals_runtime_sha256)" -check_hash "$bootstrap" "$(value poweradvantage_unit_bootstrap_sha256)" -(cd "$power" && ./gradlew "${toolchains[@]}" assemble unitBootstrapJar verifyReleaseDependencies --no-daemon --stacktrace \ - "-Pforge47MavenizerJar=$mavenizer" "-PbaseMetalsDeobfJar=$bmjar" "-PoreSpawnDeobfJar=$osjar") -git -C "$power" diff --exit-code HEAD -- -check_hash "$powerjar" "$(value poweradvantage_deobf_sha256)" -check_hash "$powerplayer" "$(value poweradvantage_runtime_sha256)" -check_hash "$agent" "$(value poweradvantage_unit_bootstrap_jar_sha256)" -curl --fail --silent --show-error --location --proto '=https' \ - 'https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.4.10/forge-1.20.1-47.4.10-installer.jar' \ - --output "$installer" -check_hash "$installer" "$(value forge_installer_sha256)" - -printf 'mavenizer=%s\norespawn=%s\norespawn_player=%s\nbasemetals=%s\nbasemetals_player=%s\npower=%s\npower_player=%s\nbootstrap=%s\nagent=%s\ninstaller=%s\n' \ - "$mavenizer" "$osjar" "$osplayer" "$bmjar" "$bmplayer" "$powerjar" "$powerplayer" "$bootstrap" "$agent" "$installer" >> "$GITHUB_OUTPUT" diff --git a/.github/verify-published-pins.sh b/.github/verify-published-pins.sh index 206980c..a949ce1 100644 --- a/.github/verify-published-pins.sh +++ b/.github/verify-published-pins.sh @@ -6,28 +6,55 @@ value() { sed -n "s/^$1=//p" gradle.properties | tr -d '\r'; } require_merged() { local repo="$1" ref="$2" status [[ "$ref" =~ ^[a-f0-9]{40}$ ]] - status="$(gh api "repos/MinecraftModDevelopmentMods/$repo/compare/$ref...master-1.20.1" --jq '.status')" + status="$(gh api "repos/MinecraftModDevelopmentMods/$repo/compare/$ref...master-1.20.6" --jq '.status')" case "$status" in identical|ahead) ;; - *) echo "::error::$repo $ref is not on upstream master-1.20.1 ($status)."; exit 1 ;; + *) echo "::error::$repo $ref is not on upstream master-1.20.6 ($status)."; exit 1 ;; esac } -file_id="$(value poweradvantage_public_file_id)" -expected="$(value poweradvantage_runtime_sha256)" -if [[ ! "$file_id" =~ ^[1-9][0-9]*$ || ! "$expected" =~ ^[A-F0-9]{64}$ ]]; then - echo '::error::A verified public basePower 1.20.1 file ID and player checksum are required.' - exit 1 -fi -require_merged basePower "$(value poweradvantage_source_ref)" +download() { + local url="$1" expected="$2" path="$3" + [[ "$expected" =~ ^[A-F0-9]{64}$ ]] + curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \ + --retry 3 --output "$path" "$url" + printf '%s %s\n' "$expected" "$path" | sha256sum -c - +} + +public_jar() { + local name="$1" project="$2" id="$3" sha="$4" jar="$5" + if [[ ! "$id" =~ ^[1-9][0-9]*$ ]]; then + echo "::error::A verified public $name file ID is required." + exit 1 + fi + download "https://www.curseforge.com/api/v1/mods/$project/files/$id/download" "$sha" "$jar" +} + +power_ref="$(value poweradvantage_source_ref)" +orespawn_ref="$(value orespawn_source_commit)" +require_merged basePower "$power_ref" require_merged BaseMetals "$(value basemetals_source_commit)" +require_merged OreSpawn "$orespawn_ref" + +inputs="${RUNNER_TEMP:?}/forge50-release-dependencies" +mkdir -p "$inputs" +power="$inputs/basePower-$(value poweradvantage_version).jar" +metals="$inputs/BaseMetals-$(value basemetals_version).jar" +orespawn="$inputs/OreSpawn-$(value orespawn_version).jar" +public_jar basePower 1780140 "$(value poweradvantage_public_file_id)" "$(value poweradvantage_deobf_sha256)" "$power" +public_jar BaseMetals 240967 "$(value basemetals_public_file_id)" "$(value basemetals_deobf_sha256)" "$metals" +public_jar OreSpawn 245586 "$(value orespawn_public_file_id)" "$(value orespawn_deobf_sha256)" "$orespawn" -player="${RUNNER_TEMP:?}/basePower-public-player.jar" -curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \ - --output "$player" "https://www.curseforge.com/api/v1/mods/1780140/files/$file_id/download" -read -r actual _ < <(sha256sum < "$player") -if [[ "${actual^^}" != "$expected" ]]; then - echo "::error::Public basePower file $file_id SHA-256 is ${actual^^}, expected $expected." - exit 1 -fi -printf 'power_player=%s\n' "$player" >> "${GITHUB_OUTPUT:?}" +installer="$inputs/forge-1.20.6-50.2.0-installer.jar" +download 'https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.6-50.2.0/forge-1.20.6-50.2.0-installer.jar' \ + "$(value forge_installer_sha256)" "$installer" +{ + printf 'power_ref=%s\n' "$power_ref" + printf 'orespawn_ref=%s\n' "$orespawn_ref" +} >> "${GITHUB_OUTPUT:?}" +{ + printf 'POWER_PLAYER=%s\n' "$power" + printf 'METALS_PLAYER=%s\n' "$metals" + printf 'ORESPAWN_PLAYER=%s\n' "$orespawn" + printf 'FORGE_INSTALLER=%s\n' "$installer" +} >> "${GITHUB_ENV:?}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 258f36d..7ed04f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,124 +1,108 @@ -name: baseElectric 1.20.1 CI +name: baseElectric 1.20.6 CI on: push: - branches: [master-1.20.1, 'feature/**'] + branches: [master-1.20.6, 'feature/**'] pull_request: - branches: [master-1.20.1] + branches: [master-1.20.6] permissions: contents: read concurrency: - group: baseelectric-1.20.1-${{ github.workflow }}-${{ github.ref }} + group: baseelectric-1.20.6-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: name: Build, test, and audit runs-on: ubuntu-latest - timeout-minutes: 105 + timeout-minutes: 75 steps: - name: Check out baseElectric uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Use canonical LF dependency inputs run: git config --global core.autocrlf false - - name: Verify merged dependency pins and public basePower bytes + - name: Verify merged and public dependency pins id: public-pins env: GH_TOKEN: ${{ github.token }} run: bash .github/verify-published-pins.sh - - name: Require coordinated 1.20.1 dependency pins - id: pins - run: bash .github/scripts/forge47-dependencies.sh pins - - name: Check out pinned OreSpawn + - name: Check out pinned OreSpawn tool source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/OreSpawn - ref: ${{ steps.pins.outputs.orespawn_ref }} + ref: ${{ steps.public-pins.outputs.orespawn_ref }} path: .ci-dependencies/OreSpawn - - name: Check out pinned Base Metals - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - repository: MinecraftModDevelopmentMods/BaseMetals - ref: ${{ steps.pins.outputs.basemetals_ref }} - path: .ci-dependencies/BaseMetals - - name: Check out pinned basePower + - name: Check out released basePower source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/basePower - ref: ${{ steps.pins.outputs.power_ref }} - path: .ci-dependencies/PowerAdvantage - - name: Install pinned Java 25 Mavenizer runtime + ref: ${{ steps.public-pins.outputs.power_ref }} + path: .ci-dependencies/basePower + - name: Install Java 25 for Mavenizer uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: '25.0.3+9.0.LTS' - - name: Install Java 8 build utilities + - name: Install Java 8 for the launcher helper uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: '8.0.502+7' - - name: Install Java 17 for Gradle and production + - name: Install Java 21 for Gradle and production uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin - java-version: '17.0.1+12' + java-version: '21.0.7+6.0.LTS' - name: Use pinned build toolchains - shell: bash run: >- 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.20.1 dependency chain - id: dependencies - run: bash .github/scripts/forge47-dependencies.sh build - - name: Build and audit release artifacts + - name: Verify the Forge 50 build inputs shell: bash env: - MAVENIZER: ${{ steps.dependencies.outputs.mavenizer }} - POWER_DEV: ${{ steps.dependencies.outputs.power }} - POWER_PLAYER: ${{ steps.public-pins.outputs.power_player }} - POWER_BOOTSTRAP: ${{ steps.dependencies.outputs.bootstrap }} - POWER_AGENT: ${{ steps.dependencies.outputs.agent }} - METALS_DEV: ${{ steps.dependencies.outputs.basemetals }} - METALS_PLAYER: ${{ steps.dependencies.outputs.basemetals_player }} - ORESPAWN_DEV: ${{ steps.dependencies.outputs.orespawn }} - ORESPAWN_PLAYER: ${{ steps.dependencies.outputs.orespawn_player }} - FORGE_INSTALLER: ${{ steps.dependencies.outputs.installer }} + ORESPAWN_REF: ${{ steps.public-pins.outputs.orespawn_ref }} + POWER_REF: ${{ steps.public-pins.outputs.power_ref }} + run: | + set -euo pipefail + orespawn="$GITHUB_WORKSPACE/.ci-dependencies/OreSpawn" + power="$GITHUB_WORKSPACE/.ci-dependencies/basePower" + test "$(git -C "$orespawn" rev-parse HEAD)" = "$ORESPAWN_REF" + test "$(git -C "$power" rev-parse HEAD)" = "$POWER_REF" + mavenizer="$orespawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar" + printf '%s %s\n' '4B14145595E900F178A082F2253A756F63897E6F61C2B8B5E7C819B82CD79E8C' "$mavenizer" | sha256sum -c - + echo "MAVENIZER=$mavenizer" >> "$GITHUB_ENV" + - name: Build and audit release artifacts + shell: bash run: | - ./gradlew $MMD_GRADLE_TOOLCHAINS build writeReleaseChecksums verifyEclipseProductionClasspath \ - "-Pforge47MavenizerJar=$MAVENIZER" "-PpowerAdvantageDeobfJar=$POWER_DEV" \ - "-PpowerAdvantageRuntimeJar=$POWER_PLAYER" "-PpowerAdvantageUnitBootstrapSource=$POWER_BOOTSTRAP" \ - "-PpowerAdvantageUnitBootstrapJar=$POWER_AGENT" "-PbaseMetalsDeobfJar=$METALS_DEV" \ - "-PbaseMetalsRuntimeJar=$METALS_PLAYER" "-PoreSpawnDeobfJar=$ORESPAWN_DEV" \ - "-PoreSpawnRuntimeJar=$ORESPAWN_PLAYER" "-PforgeInstallerJar=$FORGE_INSTALLER" \ - --no-build-cache --no-daemon --stacktrace + ./gradlew $MMD_GRADLE_TOOLCHAINS clean check build javadoc verifyReleaseDependencies verifyReleaseArtifacts \ + writeReleaseChecksums verifyEclipseProductionClasspath --no-build-cache --no-daemon --stacktrace \ + "-Pforge50MavenizerJar=$MAVENIZER" "-PpowerAdvantageDeobfJar=$POWER_PLAYER" \ + "-PbaseMetalsDeobfJar=$METALS_PLAYER" "-PoreSpawnDeobfJar=$ORESPAWN_PLAYER" \ + "-PforgeInstallerJar=$FORGE_INSTALLER" - name: Upload audited release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: baseElectric-1.20.1-${{ github.sha }} + name: baseElectric-1.20.6-${{ github.sha }} if-no-files-found: error retention-days: 30 path: | - build/libs/baseElectric-2.2.13.120011.jar - build/libs/baseElectric-2.2.13.120011-sources.jar - build/libs/baseElectric-2.2.13.120011-javadoc.jar + build/libs/baseElectric-2.2.14.120061.jar + build/libs/baseElectric-2.2.14.120061-sources.jar + build/libs/baseElectric-2.2.14.120061-javadoc.jar build/release/SHA256SUMS CHANGELOG.txt - name: Upload diagnostics on failure if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: baseElectric-1.20.1-diagnostics-${{ github.sha }} + name: baseElectric-1.20.6-diagnostics-${{ github.sha }} if-no-files-found: ignore retention-days: 14 path: | build/test-results/** build/reports/** - build/*-run/logs/** - build/problems/** - .ci-dependencies/PowerAdvantage/build/reports/** - .ci-dependencies/PowerAdvantage/build/libs-dev/*.jar diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 033e10b..5ca33bd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,94 +2,92 @@ name: CodeQL on: push: - branches: [master-1.20.1, 'feature/**'] + branches: [master-1.20.6, 'feature/**'] pull_request: - branches: [master-1.20.1] - schedule: - - cron: '59 7 * * 4' + branches: [master-1.20.6] permissions: - actions: read contents: read + actions: read security-events: write +concurrency: + group: baseelectric-1.20.6-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: analyze: name: Analyze Java runs-on: ubuntu-latest - timeout-minutes: 105 + timeout-minutes: 75 steps: - name: Check out baseElectric uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Use canonical LF dependency inputs run: git config --global core.autocrlf false - - name: Verify merged dependency pins and public basePower bytes + - name: Verify merged and public dependency pins id: public-pins env: GH_TOKEN: ${{ github.token }} run: bash .github/verify-published-pins.sh - - name: Require coordinated 1.20.1 dependency pins - id: pins - run: bash .github/scripts/forge47-dependencies.sh pins - - name: Check out pinned OreSpawn + - name: Check out pinned OreSpawn tool source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/OreSpawn - ref: ${{ steps.pins.outputs.orespawn_ref }} + ref: ${{ steps.public-pins.outputs.orespawn_ref }} path: .ci-dependencies/OreSpawn - - name: Check out pinned Base Metals - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - with: - repository: MinecraftModDevelopmentMods/BaseMetals - ref: ${{ steps.pins.outputs.basemetals_ref }} - path: .ci-dependencies/BaseMetals - - name: Check out pinned basePower + - name: Check out released basePower source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: MinecraftModDevelopmentMods/basePower - ref: ${{ steps.pins.outputs.power_ref }} - path: .ci-dependencies/PowerAdvantage - - name: Install pinned Java 25 Mavenizer runtime + ref: ${{ steps.public-pins.outputs.power_ref }} + path: .ci-dependencies/basePower + - name: Install Java 25 for Mavenizer uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: '25.0.3+9.0.LTS' - - name: Install Java 8 build utilities + - name: Install Java 8 for the launcher helper uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: '8.0.502+7' - - name: Install Java 17 for Gradle and production + - name: Install Java 21 for Gradle and production uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin - java-version: '17.0.1+12' + java-version: '21.0.7+6.0.LTS' - name: Use pinned build toolchains - shell: bash run: >- 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.20.1 dependency chain - id: dependencies - run: bash .github/scripts/forge47-dependencies.sh build + - name: Verify the Forge 50 build inputs + shell: bash + env: + ORESPAWN_REF: ${{ steps.public-pins.outputs.orespawn_ref }} + POWER_REF: ${{ steps.public-pins.outputs.power_ref }} + run: | + set -euo pipefail + orespawn="$GITHUB_WORKSPACE/.ci-dependencies/OreSpawn" + power="$GITHUB_WORKSPACE/.ci-dependencies/basePower" + test "$(git -C "$orespawn" rev-parse HEAD)" = "$ORESPAWN_REF" + test "$(git -C "$power" rev-parse HEAD)" = "$POWER_REF" + mavenizer="$orespawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar" + printf '%s %s\n' '4B14145595E900F178A082F2253A756F63897E6F61C2B8B5E7C819B82CD79E8C' "$mavenizer" | sha256sum -c - + echo "MAVENIZER=$mavenizer" >> "$GITHUB_ENV" - name: Initialize CodeQL uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4 with: languages: java-kotlin build-mode: manual - - name: Compile baseElectric production code + - name: Compile production code shell: bash - env: - MAVENIZER: ${{ steps.dependencies.outputs.mavenizer }} - POWER_DEV: ${{ steps.dependencies.outputs.power }} - METALS_DEV: ${{ steps.dependencies.outputs.basemetals }} - ORESPAWN_DEV: ${{ steps.dependencies.outputs.orespawn }} run: | ./gradlew $MMD_GRADLE_TOOLCHAINS classes verifyReleaseDependencies --rerun-tasks --no-build-cache --no-daemon --stacktrace \ - "-Pforge47MavenizerJar=$MAVENIZER" "-PpowerAdvantageDeobfJar=$POWER_DEV" \ - "-PbaseMetalsDeobfJar=$METALS_DEV" "-PoreSpawnDeobfJar=$ORESPAWN_DEV" + "-Pforge50MavenizerJar=$MAVENIZER" "-PpowerAdvantageDeobfJar=$POWER_PLAYER" \ + "-PbaseMetalsDeobfJar=$METALS_PLAYER" "-PoreSpawnDeobfJar=$ORESPAWN_PLAYER" - name: Analyze uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4 diff --git a/.github/workflows/validate-gradle-build.yml b/.github/workflows/validate-gradle-build.yml index 2d52c08..2c47d12 100644 --- a/.github/workflows/validate-gradle-build.yml +++ b/.github/workflows/validate-gradle-build.yml @@ -3,11 +3,11 @@ name: Validate Gradle Wrapper on: push: branches: - - master-1.19.4 + - master-1.20.6 - 'feature/**' pull_request: branches: - - master-1.19.4 + - master-1.20.6 permissions: contents: read diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 104d8ca..be985b5 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,10 @@ +baseElectric 2.2.14.120061 (Minecraft 1.20.6 / Forge) + +- Bring baseElectric to Minecraft 1.20.6 and Java 21 with basePower 2.4.13.120061. +- Keep saved machine state, battery charge, drill orientation and the shared creative tab. +- Keep material recipes available when their ingredients are installed. +- Use the fixed basePower renderer for fluid gauges in electric machines. + baseElectric 2.2.13.120011 (Minecraft 1.20.1 / Forge) - Update to Forge 47.4.10 with Java 17. diff --git a/README.md b/README.md index f71ee28..0719139 100644 --- a/README.md +++ b/README.md @@ -4,64 +4,63 @@ baseElectric continues DrCyano's Electric Advantage. It adds electric machines, generation, storage, automation and defence to basePower. Its equipment appears in the shared basePower creative tab. -This branch targets Minecraft **1.20.1** with Forge **47.4.10**, official mappings, -ForgeGradle **7.0.34**, and Java **17**. The version is **2.2.13.120011**. -Registry names, machine save data, and legacy Electric Advantage migration -mappings are unchanged. +This version targets Minecraft **1.20.6**, Forge **50.2.0**, official mappings, +ForgeGradle **7.0.34**, and Java **21**. The version is **2.2.14.120061**. +Install [basePower 2.4.13.120061](https://www.curseforge.com/minecraft/mc-mods/basepower/files/9545972) +for Minecraft 1.20.6. CurseForge also installs +[Base Metals](https://www.curseforge.com/minecraft/mc-mods/base-metals); this +build was tested with 3.1.2.120061 and OreSpawn 4.1.0.120061. +See the [1.20.6 notes](docs/NATIVE1206.md) for save compatibility and test coverage. Back up your world and try the upgrade on a copy. Replace Electric Advantage and Power Advantage with baseElectric and basePower; do not install both sets. ## Building locally -Use Java 17 for Gradle, the game and Eclipse Buildship. ForgeGradle uses Java 25 -for Mavenizer and Java 8 for its Slime Launcher tooling. If necessary, supply -`-Porg.gradle.java.installations.paths=,,`. -Use an isolated Gradle user home for clean-room checks. +Use Temurin 21.0.7+6 for Gradle and Minecraft. The pinned OreSpawn Mavenizer +fixture uses Java 25, and ForgeGradle's Slime Launcher tooling uses Java 8. Set +`-Porg.gradle.java.installations.paths=,,` +if Gradle cannot discover all three. -Pass the following input paths to the Gradle wrapper. Each input is checked against -the version and SHA-256 recorded in `gradle.properties`. -Hosted release checks also require the merged basePower source and a matching -public player download. +The independent Forge/resource checks do not require sibling jars: ```text --PpowerAdvantageDeobfJar="/path/to/basePower-2.4.12.120011-deobf.jar" --PpowerAdvantageRuntimeJar="/path/to/basePower-2.4.12.120011.jar" --PpowerAdvantageUnitBootstrapSource="/path/to/ForgeCapabilityBootstrap.java" --PpowerAdvantageUnitBootstrapJar="/path/to/forge-native-unit-bootstrap.jar" --PbaseMetalsDeobfJar="/path/to/BaseMetals-3.1.2.120011-deobf.jar" --PbaseMetalsRuntimeJar="/path/to/BaseMetals-3.1.2.120011.jar" --PforgeInstallerJar="/path/to/forge-1.20.1-47.4.10-installer.jar" +./gradlew --offline nativeResourceChecks verifyRecipeTagGuards processResources +node tools/verify-native-port.js +node tools/generate-recipe-unlocks.js --check ``` -By default the OreSpawn development and player jars, and its audited Forge 47 -Mavenizer fixture, come from the sibling `MinecraftMineralogy/OS1201/OreSpawn` -checkout. Use `-PoreSpawnDeobfJar`, `-PoreSpawnRuntimeJar` and -`-Pforge47MavenizerJar` to point to the exact same inputs in another layout. -For a prepared offline cache, use `--offline` and -`ORESPAWN_MAVENIZER_OFFLINE=true`. +For the full local build, supply the files matching the pins in `gradle.properties`: ```text -./gradlew clean check build javadoc verifyLocalRuntimeInputs writeReleaseChecksums verifyEclipseProductionClasspath --no-build-cache -node tools/verify-native-port.js -node tools/generate-recipe-unlocks.js --check +-PpowerAdvantageRuntimeJar=/path/to/basePower-2.4.13.120061.jar +-PbaseMetalsRuntimeJar=/path/to/BaseMetals-3.1.2.120061.jar +-PforgeInstallerJar=/path/to/forge-1.20.6-50.2.0-installer.jar +``` + +Forge 50 uses the ordinary native jar for both play and development. The former +`*DeobfJar` path flags remain aliases for the same bytes. OreSpawn and the +Mavenizer fixture default to the sibling `MinecraftMineralogy/OS1206/OreSpawn` +checkout. Use `-PoreSpawnRuntimeJar` and `-Pforge50MavenizerJar` to override paths. +For the prepared cache, use `--offline` with `ORESPAWN_MAVENIZER_OFFLINE=true`. + +```text +./gradlew check build javadoc verifyLocalRuntimeInputs writeReleaseChecksums verifyEclipseProductionClasspath --no-build-cache ``` -Use `gradlew.bat` on Windows. The player, sources and Javadoc jars go to -`build/libs`; the deobfuscated jar goes to `build/libs-dev`. The test agent is -used only by the unit tests. basePower, Base Metals and OreSpawn remain separate -mods. Base Metals is optional in Forge metadata and remains required on -CurseForge. +Use `gradlew.bat` on Windows. Output jars go to `build/libs`. Dependencies +remain separate mods. The 1.20.6 CI jobs check against the pinned Forge 50 +runtime and public dependencies. -## Eclipse and testing +## Verification -Import this checkout as an existing Gradle project named `ElectricAdvantage`. -Use the generated `runClient.launch` or `runServer.launch` after -`verifyEclipseProductionClasspath`. The build checks package paths against -Gradle and Eclipse source roots and keeps test classes out of production runs. -`tools/verification/Verify-ElectricEcj.ps1` independently compiles and runs the -test inventory using Eclipse's compiler. +Run `runGameTestServer` with the same pinned mod inputs, an existing accepted +EULA passed as `-PelectricGameTestEula=`, and a new directory passed as +`-PelectricGameTestRunDirectory=build/port-evidence/`. The test code and +its structure are not in the production jar. -The [1.19.4 notes](docs/NATIVE119.md) and [1.18.2 notes](docs/NATIVE118.md) are -historical. To check a world upgrade, test only a disposable copy. A build and -resource audit do not substitute for a migration, gameplay or client check. +Run the packaged smoke script only with the exact pinned jars, a matching Forge +server seed and an already accepted EULA. It stages launcher files only and +creates a fresh loopback-only world under `build/port-evidence`. For an upgrade, +use a separate disposable copy of a world. Neither a build nor this smoke +substitutes for manual gameplay or client verification. diff --git a/build.gradle b/build.gradle index 5e3d715..0257a83 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,6 @@ plugins { id 'eclipse' id 'idea' id 'maven-publish' - id 'net.minecraftforge.renamer' version '1.1.5' id 'net.minecraftforge.gradle' version '7.0.34' } @@ -62,13 +61,11 @@ def pinnedFile = { String property, String expected, String fallback = null -> input } -ext.forge47MavenizerDefault = - '../../../../MinecraftMineralogy/OS1201/OreSpawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar' -apply from: 'gradle/forge47-mavenizer.gradle' +apply from: 'gradle/forge50-mavenizer.gradle' java { toolchain { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } withSourcesJar() @@ -77,44 +74,23 @@ java { tasks.withType(JavaCompile).configureEach { javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } - options.release = 17 + options.release = 21 options.encoding = 'UTF-8' options.compilerArgs.addAll(['-Xmaxerrs', '1000']) } -def unitBootstrapSource = providers.provider { - pinnedFile('powerAdvantageUnitBootstrapSource', project.poweradvantage_unit_bootstrap_sha256) -} -def unitBootstrapInput = providers.provider { - pinnedFile('powerAdvantageUnitBootstrapJar', project.poweradvantage_unit_bootstrap_jar_sha256) -} -def unitBootstrapOutput = layout.buildDirectory.file('unit-bootstrap/forge-native-unit-bootstrap.jar') -def unitBootstrapJar = tasks.register('unitBootstrapJar', Copy) { - inputs.file(unitBootstrapSource) - from(unitBootstrapInput) { rename { 'forge-native-unit-bootstrap.jar' } } - into layout.buildDirectory.dir('unit-bootstrap') -} - tasks.named('test', Test) { - dependsOn unitBootstrapJar - inputs.file(unitBootstrapOutput) - doFirst { - File agent = unitBootstrapOutput.get().asFile - if (sha256Of(agent) != project.poweradvantage_unit_bootstrap_jar_sha256) { - throw new GradleException('The copied unit agent does not match the basePower checkpoint.') - } - jvmArgs "-javaagent:${agent}" - } javaLauncher = javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } afterSuite { descriptor, result -> - if (!descriptor.parent && (result.testCount != 99 || result.skippedTestCount != 0)) { - throw new GradleException("Expected 99 tests with no skips, got ${result.testCount} tests and ${result.skippedTestCount} skips") + if (!descriptor.parent && filter.includePatterns.empty && filter.commandLineIncludePatterns.empty + && (result.testCount != 102 || result.skippedTestCount != 0)) { + throw new GradleException("Expected 102 tests with no skips, got ${result.testCount} tests and ${result.skippedTestCount} skips") } } } @@ -145,7 +121,24 @@ def normalizeArchiveLineEndings = { details -> eof: FixCrLfFilter.AddAsisRemove.newInstance('asis')) } +def electricGameTestRunDirectory = layout.projectDirectory.dir( + providers.gradleProperty('electricGameTestRunDirectory').getOrElse('build/port-evidence/game-test-run')) +sourceSets { + gameTestValidation { + java.srcDir 'src/gametest/java' + compileClasspath += sourceSets.main.output + runtimeClasspath += sourceSets.main.output + } +} +configurations { + gameTestValidationImplementation.extendsFrom implementation + gameTestValidationCompileOnly.extendsFrom compileOnly + gameTestValidationRuntimeOnly.extendsFrom runtimeOnly +} +def gameTestModOutput = layout.buildDirectory.dir('forge-run-mod-classes/gametest') + minecraft { + if (gradle.startParameter.offline) mavenizerArguments.add('--cache-only') mappings channel: project.mapping_channel, version: project.mapping_version String configuredRunDirectory = providers.gradleProperty('electricAdvantageRunDirectory') .getOrElse('run') @@ -165,6 +158,12 @@ minecraft { register('server') { args '--nogui' } + register('gameTestServer') { + workingDir.set(electricGameTestRunDirectory) + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id + mods { baseelectric { source sourceSets.gameTestValidation } } + environment 'MOD_CLASSES', "${mod_id}%%${gameTestModOutput.get().asFile}" + } register('data') { workingDir.convention layout.projectDirectory.dir('run-data') args '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/'), @@ -181,22 +180,70 @@ 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.20.1 launches.' + description = 'Merges classes and processed resources for Forge 1.20.6 launches.' dependsOn tasks.named('classes') from sourceSets.main.output into forgeRunModClassesDirectory } +def gameTestStructures = layout.buildDirectory.dir('generated-electric-gametest') +def emptyGameTestStructure = layout.projectDirectory.file('src/gametest/resources/gameteststructures/empty.snbt') +def encodeElectricGameTestStructure = tasks.register('encodeElectricGameTestStructure', JavaExec) { + dependsOn tasks.named('gameTestValidationClasses') + classpath = sourceSets.gameTestValidation.runtimeClasspath + mainClass = 'zone.moddev.mc.baseelectric.gametest.ElectricGameTests' + def structure = gameTestStructures.map { it.file('data/baseelectric/structures/empty.nbt') } + inputs.file(emptyGameTestStructure) + outputs.file(structure) + args emptyGameTestStructure.asFile.absolutePath, structure.get().asFile.absolutePath +} +def prepareElectricGameTestMod = tasks.register('prepareElectricGameTestMod', Sync) { + dependsOn tasks.named('classes'), encodeElectricGameTestStructure + from sourceSets.main.output, sourceSets.gameTestValidation.output + from gameTestStructures + into gameTestModOutput +} +def prepareElectricGameTestFixture = tasks.register('prepareElectricGameTestFixture') { + doLast { + File directory = electricGameTestRunDirectory.asFile.canonicalFile + if (!directory.toPath().startsWith(layout.buildDirectory.dir('port-evidence').get().asFile.canonicalFile.toPath()) + || directory.exists()) { + throw new GradleException('Use a new GameTest run directory inside build/port-evidence.') + } + String eulaPath = providers.gradleProperty('electricGameTestEula').getOrElse('') + if (!eulaPath || !file(eulaPath).isFile() || !(file(eulaPath).text =~ /(?m)^eula=true\s*$/).find()) { + throw new GradleException('Pass an existing accepted EULA with -PelectricGameTestEula=.') + } + if (!directory.mkdirs()) throw new GradleException("Cannot create GameTest directory ${directory}") + new File(directory, 'eula.txt').text = 'eula=true\n' + new File(directory, 'server.properties').text = 'online-mode=false\nserver-ip=127.0.0.1\nserver-port=0\n' + File config = new File(directory, 'config') + config.mkdirs() + new File(config, 'fml.toml').text = 'versionCheck = false\n' + } +} tasks.withType(JavaExec).configureEach { if (name in ['runClient', 'runServer', 'runData']) { dependsOn prepareForgeRunModClasses } + if (name == 'runGameTestServer') { + dependsOn prepareElectricGameTestMod, prepareElectricGameTestFixture + doFirst { + Set splitOutputs = sourceSets.collectMany { it.output.files }.collect { it.canonicalFile } as Set + classpath = files(gameTestModOutput, classpath.files.findAll { !splitOutputs.contains(it.canonicalFile) }) + } + } } repositories { minecraft.mavenizer(it) maven fg.forgeMaven maven fg.minecraftLibsMaven + exclusiveContent { + forRepository { maven { url = 'https://repo.spongepowered.org/repository/maven-public' } } + filter { includeGroupAndSubgroups('org.spongepowered') } + } mavenCentral() + maven { url = 'https://libraries.minecraft.net/' } } def committedPins = new Properties() @@ -217,40 +264,44 @@ def requirePowerPin = { || !(project.poweradvantage_source_ref ==~ /[a-f0-9]{40}/) || ![project.poweradvantage_deobf_sha256, project.poweradvantage_runtime_sha256] .every { it ==~ /[A-F0-9]{64}/ }) { - throw new GradleException('The owner-approved basePower 2.4.12.120011 source and artifact pins are required.') - } -} -def requireCompletePowerPin = { - requirePowerPin() - if (![project.poweradvantage_unit_bootstrap_sha256, project.poweradvantage_unit_bootstrap_jar_sha256] - .every { it ==~ /[A-F0-9]{64}/ }) { - throw new GradleException('The exact basePower unit bootstrap source and jar pins are required for release.') + throw new GradleException('The owner-approved basePower 1.20.6 source and artifact pins are required.') } } - // Resolve and check only the dependencies required by the selected tasks. def powerAdvantageDeobfJar = providers.provider { requirePowerPin() - pinnedFile('powerAdvantageDeobfJar', project.poweradvantage_deobf_sha256) + pinnedFile('powerAdvantageDeobfJar', project.poweradvantage_deobf_sha256, + providers.gradleProperty('powerAdvantageRuntimeJar').orNull) } def baseMetalsDeobfJar = providers.provider { requireCommittedPins('basemetals_') - pinnedFile('baseMetalsDeobfJar', project.basemetals_deobf_sha256) + pinnedFile('baseMetalsDeobfJar', project.basemetals_deobf_sha256, + providers.gradleProperty('baseMetalsRuntimeJar').orNull) } -def oreSpawnProject = '../../../../MinecraftMineralogy/OS1201/OreSpawn' +def oreSpawnProject = '../../../../MinecraftMineralogy/OS1206/OreSpawn' def oreSpawnDeobfJar = providers.provider { requireCommittedPins('orespawn_') pinnedFile('oreSpawnDeobfJar', project.orespawn_deobf_sha256, - "${oreSpawnProject}/build/libs-dev/OreSpawn-${project.orespawn_version}-deobf.jar") + providers.gradleProperty('oreSpawnRuntimeJar').getOrElse( + "${oreSpawnProject}/build/libs/OreSpawn-${project.orespawn_version}.jar")) +} + +// An older 1.20.6 API jar may be used for javac only; it cannot qualify a runtime. +def baseMetalsCompileApiJar = providers.gradleProperty('baseMetalsCompileApiJar') +def baseMetalsCompileJar = providers.provider { + if (!baseMetalsCompileApiJar.isPresent()) return baseMetalsDeobfJar.get() + pinnedFile('baseMetalsCompileApiJar', + '08AC265C7284D18962A3DE91B7C267187AEF76ACF6AFE7BBA0729F5CED60A437') } +def nativeForge = minecraft.dependency( + "net.minecraftforge:forge:${project.minecraft_version}-${project.forge_version}") dependencies { - implementation minecraft.dependency( - "net.minecraftforge:forge:${project.minecraft_version}-${project.forge_version}") + implementation nativeForge // basePower is required at runtime but remains a separate mod jar. compileOnly files(powerAdvantageDeobfJar) runtimeOnly files(powerAdvantageDeobfJar) - compileOnly files(baseMetalsDeobfJar) + compileOnly files(baseMetalsCompileJar) runtimeOnly files(baseMetalsDeobfJar) // Required transitively by the coordinated PowerAdvantage/Base Metals development runtime. compileOnly files(oreSpawnDeobfJar) @@ -259,6 +310,35 @@ dependencies { testImplementation files(powerAdvantageDeobfJar, baseMetalsDeobfJar, oreSpawnDeobfJar) } +// Run the data and native codec checks even while the sibling mods are being built. +def nativeResourceCheckInputs = configurations.dependencyScope('nativeResourceCheckInputs') +def nativeResourceCheckClasspath = configurations.resolvable('nativeResourceCheckClasspath') { + extendsFrom nativeResourceCheckInputs.get() + attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) +} +dependencies { + add('nativeResourceCheckInputs', nativeForge) + add('nativeResourceCheckInputs', 'junit:junit:4.13.2') +} +def nativeResourceCheckClasses = layout.buildDirectory.dir('classes/native-resource-checks') +def compileNativeResourceChecks = tasks.register('compileNativeResourceChecks', JavaCompile) { + source fileTree('src/test/java') { + include '**/BlockLootResourceTest.java', '**/RecipeResourceTest.java', + '**/RecipeUnlockContractTest.java', + '**/RecipeRegistrationThreadTest.java', '**/NativeTestBootstrap.java', '**/LegacyBatteryDataTest.java' + } + classpath = nativeResourceCheckClasspath.get() + destinationDirectory = nativeResourceCheckClasses +} +tasks.register('nativeResourceChecks', Test) { + group = 'verification' + description = 'Checks Electric resources against native Forge 50 without sibling mod jars.' + dependsOn compileNativeResourceChecks + useJUnit() + testClassesDirs = files(nativeResourceCheckClasses) + classpath = testClassesDirs + nativeResourceCheckClasspath.get() +} + tasks.named('processResources', ProcessResources) { filteringCharset = 'UTF-8' inputs.properties([ @@ -292,15 +372,16 @@ def powerPinManifest = [ 'API-Pin-State' : project.poweradvantage_pin_state, 'basePower-Source-Ref' : project.poweradvantage_source_ref, 'basePower-Deobf-SHA256': project.poweradvantage_deobf_sha256, - 'basePower-Player-SHA256': project.poweradvantage_runtime_sha256, - 'basePower-Unit-Source-SHA256': project.poweradvantage_unit_bootstrap_sha256, - 'basePower-Unit-Agent-SHA256': project.poweradvantage_unit_bootstrap_jar_sha256 + 'basePower-Player-SHA256': project.poweradvantage_runtime_sha256 ] tasks.named('jar', Jar) { - doFirst { requireCompletePowerPin() } - archiveClassifier = 'deobf' - destinationDirectory = layout.buildDirectory.dir('libs-dev') + doFirst { + requirePowerPin() + if (baseMetalsCompileApiJar.isPresent()) { + throw new GradleException('The compile-only Base Metals API jar cannot package a candidate.') + } + } exclude 'fernflower_abstract_parameter_names.txt' manifest { attributes([ @@ -317,41 +398,17 @@ tasks.named('jar', Jar) { } } -def renamedJar = renamer.classes(tasks.named('jar', Jar)) { - map.from minecraft.dependency.toSrgFile - archiveClassifier = 'renamed' - output.set(layout.buildDirectory.file( - "intermediates/renamed/${base.archivesName.get()}-${project.version}.jar")) -} +def releaseJar = tasks.named('jar', Jar) -// Renamer adds an internal Fernflower parameter map. Repack its output so the -// public jar is deterministic and contains only the mod plus its own manifest. -def releaseJar = tasks.register('releaseJar', Jar) { - dependsOn renamedJar - archiveClassifier = null - destinationDirectory = layout.buildDirectory.dir('libs') - from({ zipTree(renamedJar.get().output.get().asFile) }) { - exclude 'META-INF/MANIFEST.MF' - exclude 'fernflower_abstract_parameter_names.txt' - } - manifest { - attributes([ - 'Maven-Artifact' : "${project.group}:${base.archivesName.get()}:${project.version}", - 'Specification-Title' : project.mod_id, - 'Specification-Vendor' : project.mod_authors, - 'Specification-Version' : '1', - 'Implementation-Title' : base.archivesName.get(), - 'Implementation-Version': project.version, - 'Implementation-Vendor' : project.mod_authors, - 'Built-On-Java' : project.java_version, - 'Built-On' : "${project.minecraft_version}-${project.forge_version}" - ] + powerPinManifest) - } +tasks.register('releaseJar') { + group = 'build' + description = 'Builds the native Forge 50 player jar.' + dependsOn releaseJar } tasks.register('deobfJar') { group = 'build' - description = 'Builds the deobfuscated development jar under build/libs-dev.' + description = 'Builds the same native Forge 50 jar used for development and play.' dependsOn tasks.named('jar') } @@ -382,11 +439,6 @@ tasks.named('javadocJar', Jar) { } } -['apiElements', 'runtimeElements'].each { configurationName -> - configurations.named(configurationName) { artifacts.clear() } - artifacts { add(configurationName, releaseJar) } -} - tasks.named('assemble') { dependsOn releaseJar dependsOn tasks.named('sourcesJar') @@ -403,31 +455,34 @@ tasks.register('verifyReleaseConfiguration') { group = 'verification' description = 'Validates release identity, target metadata, and dependency policy.' doLast { - requireCompletePowerPin() + requirePowerPin() + if (baseMetalsCompileApiJar.isPresent()) { + throw new GradleException('The compile-only Base Metals API jar cannot qualify a build.') + } requireCommittedPins('basemetals_') requireCommittedPins('orespawn_') def pack = new JsonSlurper().parse(file('src/main/resources/pack.mcmeta')).pack - if (pack.pack_format != 15) { - throw new GradleException('Minecraft 1.20.1 requires pack format 15') + if (pack.pack_format != 32 || pack.supported_formats != [min_inclusive: 32, max_inclusive: 41]) { + throw new GradleException('Minecraft 1.20.6 requires resource pack format 32') } - if (project.mod_version != '2.2.13.120011') { + if (project.mod_version != '2.2.14.120061') { throw new GradleException("Unexpected baseElectric release version: ${project.mod_version}") } - if (project.minecraft_version != '1.20.1' - || project.minecraft_version_range != '[1.20.1]' - || project.forge_version != '47.4.10' - || project.forge_version_range != '[47.4.10,48)' - || project.loader_version_range != '[47,)' + if (project.minecraft_version != '1.20.6' + || project.minecraft_version_range != '[1.20.6]' + || project.forge_version != '50.2.0' + || project.forge_version_range != '[50.2.0,51)' + || project.loader_version_range != '[50,)' || project.mapping_channel != 'official' - || project.mapping_version != '1.20.1' - || project.mcp_version != '20230612.114412') { + || project.mapping_version != '1.20.6' + || project.mcp_version != '20240429.135109') { throw new GradleException('Unexpected Minecraft, Forge, or mappings target') } if (project.loader_name != 'forge' || project.loader_code != '1' - || project.java_version != '17' - || project.java_toolchain_version != '17.0.1+12' - || project.java_setup_version != '17.0.1+12' - || project.gradle_java_version != '17') { + || project.java_version != '21' + || project.java_toolchain_version != '21.0.7+6' + || project.java_setup_version != '21.0.7+6.0.LTS' + || project.gradle_java_version != '21') { throw new GradleException('Unexpected release dispatcher target metadata') } if (project.mod_id != 'baseelectric' @@ -440,33 +495,34 @@ tasks.register('verifyReleaseConfiguration') { } if (project.cf_requirements != 'basepower,base-metals' || project.cf_optionals != '' - || project.cf_versions != '1.20.1') { + || project.cf_versions != '1.20.6') { throw new GradleException('Unexpected CurseForge dependency or game-version metadata') } - if (project.poweradvantage_version != '2.4.12.120011' + if (project.poweradvantage_version != '2.4.13.120061' || project.poweradvantage_source_repository != 'MinecraftModDevelopmentMods/basePower') { throw new GradleException('Unexpected basePower compile dependency identity') } - if (project.basemetals_version != '3.1.2.120011' - || project.orespawn_version != '4.1.0.120011' + if (!(project.basemetals_version ==~ /3\.\d+\.\d+\.120061/) + || project.orespawn_version != '4.1.0.120061' || !(project.basemetals_source_commit ==~ /[a-f0-9]{40}/) || !(project.basemetals_deobf_sha256 ==~ /[A-F0-9]{64}/) || !(project.basemetals_runtime_sha256 ==~ /[A-F0-9]{64}/) - || project.orespawn_source_commit != '9d9db6cd315c9fce542808aa2551c94bf9267e93' - || project.orespawn_deobf_sha256 != 'A0B096894DC48308D59455F7EC67AB0BBF7EB02354D903024A9E9E876EB07CBB' - || project.orespawn_runtime_sha256 != 'E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0' - || project.forge_installer_sha256 != '1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3') { + || !(project.orespawn_source_commit ==~ /[a-f0-9]{40}/) + || project.orespawn_deobf_sha256 != project.orespawn_runtime_sha256 + || project.basemetals_deobf_sha256 != project.basemetals_runtime_sha256 + || project.poweradvantage_deobf_sha256 != project.poweradvantage_runtime_sha256 + || project.forge_installer_sha256 != '8789098B077F5486449311A11DC05E977FEB9430913CB15F30B21A2D8AA213EA') { throw new GradleException('Unexpected native dependency pins') } String mainSource = file( 'src/main/java/zone/moddev/mc/baseelectric/ElectricAdvantage.java').getText('UTF-8') if (!mainSource.contains('MODID = "baseelectric"') - || !mainSource.contains('VERSION = "2.2.13.120011"')) { + || !mainSource.contains('VERSION = "2.2.14.120061"')) { throw new GradleException('baseElectric source identity changed') } String metadata = file('src/main/resources/META-INF/mods.toml').getText('UTF-8').replace('\r\n', '\n') ['modId="baseelectric"', 'displayName="baseElectric"', 'modId="basepower"', 'modId="basemetals"', - 'versionRange="[2.4.12.120011,3.0.0)"', 'versionRange="[3.1.2.120011,4.0.0)"'].each { marker -> + 'versionRange="[2.4.13.120061,3.0.0)"', 'versionRange="[3.1.2.120061,4.0.0)"'].each { marker -> if (!metadata.contains(marker)) { throw new GradleException("Source mods.toml is missing ${marker}") } @@ -486,7 +542,7 @@ def auditModInput = { File jarFile, String modId, String version, List r String metadata = zip.getInputStream(zip.getEntry('META-INF/mods.toml')).getText('UTF-8') if (manifest.getValue('Implementation-Version') != version || manifest.getValue('Built-On') != "${project.minecraft_version}-${project.forge_version}" - || manifest.getValue('Built-On-Java') != '17' + || manifest.getValue('Built-On-Java') != '21' || !metadata.contains("modId=\"${modId}\"") || !metadata.contains("version=\"${version}\"")) { throw new GradleException("${jarFile.name} has unexpected ${modId} version or target metadata") @@ -497,17 +553,19 @@ def auditModInput = { File jarFile, String modId, String version, List r tasks.register('verifyLocalNativeInputs') { group = 'verification' - description = 'Verifies explicit Base Metals and OreSpawn 1.20.1 development and player JARs.' + description = 'Verifies explicit Base Metals and OreSpawn 1.20.6 development and player JARs.' dependsOn tasks.named('verifyReleaseConfiguration') doLast { auditModInput(baseMetalsDeobfJar.get(), 'basemetals', project.basemetals_version, ['zone/moddev/mc/basemetals/api/migration/Legacy112MigrationExtension.class', 'zone/moddev/mc/basemetals/recipe/CrushingRecipe.class']) - auditModInput(pinnedFile('baseMetalsRuntimeJar', project.basemetals_runtime_sha256), + auditModInput(pinnedFile('baseMetalsRuntimeJar', project.basemetals_runtime_sha256, + providers.gradleProperty('baseMetalsDeobfJar').orNull), 'basemetals', project.basemetals_version, []) auditModInput(oreSpawnDeobfJar.get(), 'orespawn', project.orespawn_version, []) auditModInput(pinnedFile('oreSpawnRuntimeJar', project.orespawn_runtime_sha256, - "${oreSpawnProject}/build/libs/OreSpawn-${project.orespawn_version}.jar"), + providers.gradleProperty('oreSpawnDeobfJar').getOrElse( + "${oreSpawnProject}/build/libs/OreSpawn-${project.orespawn_version}.jar")), 'orespawn', project.orespawn_version, []) } } @@ -518,10 +576,9 @@ tasks.register('verifyLocalRuntimeInputs') { dependsOn tasks.named('verifyLocalNativeInputs') doLast { requirePowerPin() - auditModInput(pinnedFile('powerAdvantageRuntimeJar', project.poweradvantage_runtime_sha256), + auditModInput(pinnedFile('powerAdvantageRuntimeJar', project.poweradvantage_runtime_sha256, + providers.gradleProperty('powerAdvantageDeobfJar').orNull), 'basepower', project.poweradvantage_version, []) - logger.lifecycle("Verified basePower unit source: ${project.poweradvantage_unit_bootstrap_sha256} ${unitBootstrapSource.get()}") - logger.lifecycle("Verified basePower unit agent: ${project.poweradvantage_unit_bootstrap_jar_sha256} ${unitBootstrapInput.get()}") File installer = pinnedFile('forgeInstallerJar', project.forge_installer_sha256) logger.lifecycle("Verified Forge installer: ${project.forge_installer_sha256} ${installer}") } @@ -634,7 +691,7 @@ tasks.register('verifyReleaseArtifacts') { 'zone/moddev/mc/baseelectric/migration/ElectricLegacyMigrations.class', 'zone/moddev/mc/baseelectric/init/OreSpawnWorldGen.class', 'zone/moddev/mc/baseelectric/init/Villages.class', - 'zone/moddev/mc/baseelectric/recipe/RecipeConditions$ModeSerializer.class', + 'zone/moddev/mc/baseelectric/recipe/RecipeConditions$ModeCondition.class', 'assets/baseelectric/lang/en_us.json', 'data/baseelectric/loot_tables/blocks/electric_drill.json', 'data/baseelectric/loot_tables/blocks/electric_conduit.json', @@ -647,7 +704,8 @@ tasks.register('verifyReleaseArtifacts') { throw new GradleException("Release jar is missing ${required}") } } - ['agent-notes/', '.codex/', 'src/test/', 'fernflower_abstract_parameter_names.txt', + ['agent-notes/', '.codex/', 'src/test/', 'zone/moddev/mc/baseelectric/gametest/', + 'data/baseelectric/structures/empty.nbt', 'fernflower_abstract_parameter_names.txt', 'cyano/poweradvantage/', 'zone/moddev/mc/basepower/', 'zone/moddev/mc/poweradvantage/', 'zone/moddev/mc/electricadvantage/', 'assets/electricadvantage/', 'data/electricadvantage/', @@ -684,20 +742,12 @@ tasks.register('verifyReleaseArtifacts') { } } int major = ((header[6] & 0xff) << 8) | (header[7] & 0xff) - if (major != 61) { - throw new GradleException("${entry.name} uses Java class major ${major}, expected 61") + if (major != 65) { + throw new GradleException("${entry.name} uses Java class major ${major}, expected 65") } } } - new ZipFile(tasks.named('jar', Jar).get().archiveFile.get().asFile).withCloseable { zip -> - verifyPackagedBlocksAtlas(zip) - def manifest = new Manifest(zip.getInputStream(zip.getEntry('META-INF/MANIFEST.MF'))).mainAttributes - if (powerPinManifest.any { key, value -> manifest.getValue(key) != value }) { - throw new GradleException('Development JAR does not record the exact basePower pins') - } - } - new ZipFile(new File(libs, expectedReleaseFiles.get()[1])).withCloseable { sourceZip -> if (sourceZip.getEntry('zone/moddev/mc/baseelectric/ElectricAdvantage.java') == null || sourceZip.getEntry('zone/moddev/mc/baseelectric/machines/ElectricDrillTileEntity.java') == null) { @@ -832,7 +882,7 @@ tasks.register('validateMavenReleaseCredentials') { group = 'publishing' description = 'Rejects remote publication from this local port.' doLast { - throw new GradleException('Remote Maven publication is disabled on the local 1.20.1 port.') + throw new GradleException('Remote Maven publication is disabled on the local 1.20.6 port.') } } @@ -1140,8 +1190,8 @@ tasks.register('verifyEclipseProductionClasspath') { def productionJre = eclipseClasspath.classpathentry.findAll { it.@kind.text() == 'con' && it.@path.text().startsWith('org.eclipse.jdt.launching.JRE_CONTAINER/') } - if (productionJre.size() != 1 || productionJre[0].@path.text().tokenize('/').last() != 'JavaSE-17') { - throw new GradleException('Eclipse production JRE must be JavaSE-17') + if (productionJre.size() != 1 || productionJre[0].@path.text().tokenize('/').last() != 'JavaSE-21') { + throw new GradleException('Eclipse production JRE must be JavaSE-21') } def processedResources = eclipseClasspath.classpathentry.findAll { it.@kind.text() == 'src' && it.@path.text() == 'build/resources/main' @@ -1226,18 +1276,26 @@ tasks.register('verifyEclipseProductionClasspath') { String vmArguments = launch.stringAttribute.find { it.@key.text() == 'org.eclipse.jdt.launching.VM_ARGUMENTS' }.@value.text() - def legacyFile = vmArguments =~ /(?:^|\s)"-DlegacyClassPath\.file=([^"]+)"(?=\s|$)/ - if (!legacyFile.find() || !file(legacyFile.group(1)).isFile() - || !(vmArguments =~ /(?:^|\s)-p\s+"[^"]+"/).find()) { - throw new GradleException("${name} must quote the Forge classpath and module paths") - } + String mainType = launch.stringAttribute.find { + it.@key.text() == 'org.eclipse.jdt.launching.MAIN_TYPE' + }.@value.text() + String target = name == 'runClient.launch' ? 'forge_userdev_client' : 'forge_userdev_server' if (contents.contains('${MC_VERSION}') - || !programArguments.contains('--main cpw.mods.bootstraplauncher.BootstrapLauncher') - || !programArguments.contains("--fml.mcVersion ${project.minecraft_version}") - || !programArguments.contains("--fml.forgeVersion ${project.forge_version}") - || !programArguments.contains("--fml.mcpVersion ${project.mcp_version}") + || mainType != 'net.minecraftforge.launcher.Main' + || !programArguments.startsWith('--main net.minecraftforge.bootstrap.ForgeBootstrap ') + || !programArguments.contains(" -- --launchTarget ${target} ") || !vmArguments.contains('--add-opens java.base/java.lang.invoke=ALL-UNNAMED')) { - throw new GradleException("${name} does not define the native Forge 47 bootstrap and literal target versions") + throw new GradleException("${name} does not define the Forge 50 bootstrap and native launch target") + } + ['--cache', '--metadata', '--to-srg', '--to-obf'].each { option -> + def argument = programArguments =~ /(?:^|\s)${option}\s+(?:"([^"]+)"|([^"\s]+))(?=\s+--|$)/ + if (!argument.find()) { + throw new GradleException("${name} must keep ${option} as one Slime Launcher argument") + } + File path = file(argument.group(1) ?: argument.group(2)) + if (option != '--cache' && !path.isFile()) { + throw new GradleException("${name} ${option} points to a missing file: ${path}") + } } } } @@ -1403,7 +1461,7 @@ tasks.register('verifyRecipeTagGuards') { collectTags = { Object node, Set tags -> if (node instanceof Map) { node.each { key, value -> - if (key == 'conditions' || key == 'result') return + if (key == 'forge:condition' || key == 'result') return if (key == 'tag' && value instanceof String && value.startsWith('forge:')) { tags.add(value) } else { @@ -1418,12 +1476,18 @@ tasks.register('verifyRecipeTagGuards') { Map recipe = new JsonSlurper().parse(recipeFile) as Map Set tags = [] as Set collectTags(recipe, tags) - Collection conditions = (recipe.conditions ?: []) as Collection + Map condition = recipe['forge:condition'] as Map + Collection conditions = condition == null ? [] : + condition.type == 'forge:and' ? condition.values : [condition] if (conditions.any { !(it instanceof Map) }) { throw new GradleException("${recipeFile.path} contains a non-object recipe condition") } + if (conditions.any { it.type == 'forge:tag_empty' + || (it.type == 'forge:not' && it.value?.type == 'forge:tag_empty') }) { + throw new GradleException("${recipeFile.path} must use Power's content-aware tag conditions") + } Set guards = conditions - .findAll { it instanceof Map && it.type == 'basepower:tag_not_empty' } + .findAll { it.type == 'basepower:tag_not_empty' } .collect { it.tag as String } as Set Set emptyGuards = conditions.findAll { it.type == 'basepower:tag_empty' } .collect { it.tag as String } as Set diff --git a/docs/NATIVE1206.md b/docs/NATIVE1206.md new file mode 100644 index 0000000..f5515db --- /dev/null +++ b/docs/NATIVE1206.md @@ -0,0 +1,27 @@ +# Electric on Minecraft 1.20.6 + +baseElectric 2.2.14.120061 uses Forge 50.2.0, Java 21 and basePower +2.4.13.120061. The ordinary native jar is used both in a game and as a +development dependency. No companion mods are bundled. + +## Bringing an old world forward + +Back up your save and upgrade a copy. Replace Electric Advantage and Power +Advantage with baseElectric and basePower. Keep the original save for use with +the old mods. + +Machine, block and entity IDs and saved data keys have not changed. Batteries +retain their charge when legacy item data moves into Minecraft's component +format. An explicit zero still means empty; a missing charge still means full. +Drills preserve their direction, inventory, target and progress when moving +along their track. basePower's migration also reads old nested inventory items. + +## Recipes and checks + +Material-dependent recipes are available when the corresponding tags have +ingredients. Their recipe-book advancements stay loaded across recipe modes. +The live tests check machine operation, battery conversion, sulfur loot, +damage types and recipe registration. The packaged startup smoke is a +fresh-world check; it is separate from world-upgrade, restart and client tests. + +See the [README](../README.md) for the build and verification commands. diff --git a/gradle.properties b/gradle.properties index 321e7ae..810d696 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,53 +5,53 @@ org.gradle.caching=true org.gradle.parallel=false net.minecraftforge.gradle.merge-source-sets=false -minecraft_version=1.20.1 -minecraft_version_range=[1.20.1] -forge_version=47.4.10 -forge_installer_sha256=1912760B4CB6B803D8A826DE603C9076B1DA71EC2765E9A1F8C1CA78F65278E3 -forge_version_range=[47.4.10,48) -loader_version_range=[47,) +minecraft_version=1.20.6 +minecraft_version_range=[1.20.6] +forge_version=50.2.0 +forge_installer_sha256=8789098B077F5486449311A11DC05E977FEB9430913CB15F30B21A2D8AA213EA +forge_version_range=[50.2.0,51) +loader_version_range=[50,) mapping_channel=official -mapping_version=1.20.1 -mcp_version=20230612.114412 +mapping_version=1.20.6 +mcp_version=20240429.135109 loader_name=forge loader_code=1 -java_version=17 -java_toolchain_version=17.0.1+12 -java_setup_version=17.0.1+12 -gradle_java_version=17 +java_version=21 +java_toolchain_version=21.0.7+6 +java_setup_version=21.0.7+6.0.LTS +gradle_java_version=21 curseforge_project_id=1783006 mod_id=baseelectric mod_name=baseElectric mod_license=GPL-3.0-only -mod_version=2.2.13.120011 +mod_version=2.2.14.120061 mod_group=zone.moddev.mc.baseelectric mod_authors=DrCyano mod_description=Electric-powered machines and infrastructure for basePower. cf_requirements=basepower,base-metals cf_optionals= -cf_versions=1.20.1 +cf_versions=1.20.6 -poweradvantage_version=2.4.12.120011 +poweradvantage_version=2.4.13.120061 poweradvantage_pin_state=MERGED_SOURCE poweradvantage_source_repository=MinecraftModDevelopmentMods/basePower -# Build against the merged source and verify the matching public player jar. -poweradvantage_source_ref=6943b5be9478d846801ed5e7f7422df3e8f6e86a -poweradvantage_public_file_id=9540451 -poweradvantage_deobf_sha256=21A2A3007BA076D219E6836707EF365E2031823A09D5E3DC2A92DD88BD67EA01 -poweradvantage_runtime_sha256=E6835ECB04D3F2D5F54731694F7B8D87F06B4A0A9DDB18AA5EDD70EE0E1B099A -poweradvantage_unit_bootstrap_sha256=0FB05554D6446BD5561BF9DE47B9F173E6F6C28E39A2BC877D359BB363CB1ABE -poweradvantage_unit_bootstrap_jar_sha256=A93CD83EC42B09B730CB7715C10C6E53D47B22B557EFE68EDC95241D53BD4EB3 +# The Forge 50 native jar is used unchanged on both classpaths. +poweradvantage_source_ref=d1cdc73d19551786ab4524879cb9abca8c881251 +poweradvantage_public_file_id=9545972 +poweradvantage_deobf_sha256=E53BDD64776741B2EBAE36A646049DC98487E1BAD1CF69F1E3FCD95188F907F1 +poweradvantage_runtime_sha256=E53BDD64776741B2EBAE36A646049DC98487E1BAD1CF69F1E3FCD95188F907F1 -basemetals_version=3.1.2.120011 -basemetals_source_commit=b4795d413b3d356406c351c5e7e29406789f3f30 -basemetals_deobf_sha256=A67EB0CB74971E53D528C4D4F1275AE007106D7F8F71DFE4A16FB50411BDCC28 -basemetals_runtime_sha256=30FC6777300E0E48FBB63E3250E86122DAFA38CCA5AD5878CB795C72B7CCCCDE +basemetals_version=3.1.2.120061 +basemetals_source_commit=e9d92f157ee5056a31e479d5b8f9dca8f0648c12 +basemetals_public_file_id=9543397 +basemetals_deobf_sha256=6186AC62C7E2E333373EA0D8AD8DE53FF859C520EBF568DFB47517C4F77C8C5D +basemetals_runtime_sha256=6186AC62C7E2E333373EA0D8AD8DE53FF859C520EBF568DFB47517C4F77C8C5D -orespawn_version=4.1.0.120011 -orespawn_source_commit=9d9db6cd315c9fce542808aa2551c94bf9267e93 -orespawn_deobf_sha256=A0B096894DC48308D59455F7EC67AB0BBF7EB02354D903024A9E9E876EB07CBB -orespawn_runtime_sha256=E6BDE47C1BB0BF4D08396F1D1FD5B1D2D3F8A5DF09905F279D39E2601D7FE4B0 +orespawn_version=4.1.0.120061 +orespawn_source_commit=4085315345ff043448b316d75e03f4b8da45402d +orespawn_public_file_id=9183384 +orespawn_deobf_sha256=FAA7107B9FB84E2C62ED847CAFD880AA3C4238A37799BAD955EA9602A944AA26 +orespawn_runtime_sha256=FAA7107B9FB84E2C62ED847CAFD880AA3C4238A37799BAD955EA9602A944AA26 diff --git a/gradle/forge47-mavenizer.gradle b/gradle/forge47-mavenizer.gradle deleted file mode 100644 index fe80eb5..0000000 --- a/gradle/forge47-mavenizer.gradle +++ /dev/null @@ -1,27 +0,0 @@ -import java.security.MessageDigest -import org.gradle.jvm.toolchain.JvmVendorSpec - -// OreSpawn's audited fixture repairs the Forge 47 decompiled sources. -def fixturePath = providers.gradleProperty('forge47MavenizerJar').orNull -if (fixturePath == null) fixturePath = project.findProperty('forge47MavenizerDefault') -if (!fixturePath || fixturePath.isBlank()) { - throw new GradleException('Set -Pforge47MavenizerJar to the pinned OreSpawn Forge 47 Mavenizer fixture.') -} -File fixture = file(fixturePath) -if (!fixture.isFile()) { - throw new GradleException("Forge 47 Mavenizer fixture not found: ${fixture}. Use -Pforge47MavenizerJar=.") -} -def expected = '416DCA4797BC55826F0DDCF03FDC405F1990FC15C2133FA27A1F143BF7976177' -def actual = MessageDigest.getInstance('SHA-256').digest(fixture.bytes).encodeHex().toString().toUpperCase(Locale.ROOT) -if (actual != expected) { - throw new GradleException("Forge 47 Mavenizer fixture SHA-256 mismatch: expected ${expected}, got ${actual}") -} - -fgtools.configure('mavenizer') { - classpath.from(fixture) - mainClass.set('net.minecraftforge.mcmaven.cli.Main') - javaLauncher.set(javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(25) - vendor = JvmVendorSpec.ADOPTIUM - }) -} diff --git a/gradle/forge50-mavenizer.gradle b/gradle/forge50-mavenizer.gradle new file mode 100644 index 0000000..4b8176b --- /dev/null +++ b/gradle/forge50-mavenizer.gradle @@ -0,0 +1,22 @@ +import java.security.MessageDigest +import org.gradle.jvm.toolchain.JvmVendorSpec + +def fixture = file(providers.gradleProperty('forge50MavenizerJar').getOrElse( + '../../../../MinecraftMineralogy/OS1206/OreSpawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar')) +def expected = '4B14145595E900F178A082F2253A756F63897E6F61C2B8B5E7C819B82CD79E8C' +if (!fixture.isFile()) { + throw new GradleException("Missing Forge 50 Mavenizer fixture: ${fixture}. Set -Pforge50MavenizerJar=.") +} +def actual = MessageDigest.getInstance('SHA-256').digest(fixture.bytes).encodeHex().toString().toUpperCase(Locale.ROOT) +if (actual != expected) { + throw new GradleException("Forge 50 Mavenizer fixture SHA-256 mismatch: expected ${expected}, got ${actual}") +} + +fgtools.configure('mavenizer') { + classpath.from(fixture) + mainClass.set('net.minecraftforge.mcmaven.cli.Main') + javaLauncher.set(javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(25) + vendor = JvmVendorSpec.ADOPTIUM + }) +} diff --git a/src/gametest/java/zone/moddev/mc/baseelectric/gametest/ElectricGameTests.java b/src/gametest/java/zone/moddev/mc/baseelectric/gametest/ElectricGameTests.java new file mode 100644 index 0000000..e57d04b --- /dev/null +++ b/src/gametest/java/zone/moddev/mc/baseelectric/gametest/ElectricGameTests.java @@ -0,0 +1,147 @@ +package zone.moddev.mc.baseelectric.gametest; + +import io.netty.buffer.Unpooled; +import java.nio.file.Files; +import java.nio.file.Path; +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraftforge.gametest.GameTestDontPrefix; +import net.minecraftforge.gametest.GameTestHolder; +import zone.moddev.mc.baseelectric.ElectricAdvantage; +import zone.moddev.mc.baseelectric.init.Blocks; +import zone.moddev.mc.baseelectric.init.Items; +import zone.moddev.mc.baseelectric.init.Power; +import zone.moddev.mc.baseelectric.items.BatteryItem; +import zone.moddev.mc.baseelectric.machines.ElectricDrillTileEntity; +import zone.moddev.mc.baseelectric.machines.LaserTurretTileEntity; + +@GameTestHolder(value = ElectricAdvantage.MODID, namespace = ElectricAdvantage.MODID) +@GameTestDontPrefix +public final class ElectricGameTests { + private ElectricGameTests() {} + + public static void main(String[] args) throws Exception { + Path output = Path.of(args[1]); + Files.createDirectories(output.getParent()); + NbtIo.writeCompressed(NbtUtils.snbtToStructure(Files.readString(Path.of(args[0]))), output); + } + + @GameTest(batch = ElectricAdvantage.MODID, template = "empty") + public static void drillUpgradesAndTransfersLegacyBattery(GameTestHelper helper) { + BlockPos source = new BlockPos(1, 1, 1); + BlockPos destination = source.east(); + helper.setBlock(source, Blocks.laser_drill); + helper.setBlock(destination, Blocks.laser_drill); + var drill = (ElectricDrillTileEntity) helper.getBlockEntity(source); + var relocated = (ElectricDrillTileEntity) helper.getBlockEntity(destination); + var registries = helper.getLevel().registryAccess(); + CompoundTag batteryData = new CompoundTag(); + batteryData.putFloat("energy", 0.0F); + batteryData.putString("marker", "old-drill-slot"); + CompoundTag oldStack = new CompoundTag(); + oldStack.putString("id", "baseelectric:lead_acid_battery"); + oldStack.putByte("Slot", (byte) 0); + oldStack.putByte("Count", (byte) 1); + oldStack.put("tag", batteryData); + ListTag slots = new ListTag(); + slots.add(oldStack); + CompoundTag oldInventory = new CompoundTag(); + oldInventory.put("Items", slots); + drill.loadWithComponents(oldInventory, registries); + ItemStack stack = drill.getOutputSlot(0); + var battery = (BatteryItem) Items.lead_acid_battery; + helper.assertTrue(stack != null && stack.is(battery), "The legacy slot did not load as a battery"); + helper.assertTrue(battery.getEnergy(stack) == 0.0F, "The depleted battery became charged"); + helper.assertTrue(battery.addEnergy(stack, 25.0F, Power.ELECTRIC_POWER) == 25.0F, + "The loaded battery cannot receive charge"); + relocated.loadWithComponents(drill.saveWithoutMetadata(registries), registries); + ItemStack moved = relocated.getOutputSlot(0); + helper.assertTrue(moved != null && ItemStack.matches(stack, moved), + "Drill transfer did not preserve the battery components"); + helper.assertTrue("old-drill-slot".equals(moved.get(DataComponents.CUSTOM_DATA).copyTag().getString("marker")), + "Charging the battery erased unrelated data"); + helper.assertTrue(relocated.getBlockPos().equals(helper.absolutePos(destination)), + "Drill transfer changed the destination position"); + helper.succeed(); + } + + @GameTest(batch = ElectricAdvantage.MODID, template = "empty") + public static void recipeAvailabilityDoesNotRemoveDiscovery(GameTestHelper helper) { + var server = helper.getLevel().getServer(); + var advancement = ResourceLocation.fromNamespaceAndPath(ElectricAdvantage.MODID, "recipes/alkaline_battery"); + helper.assertTrue(server.getAdvancements().get(advancement) != null, + "A material-gated recipe lost its discovery advancement"); + int checked = 0; + var registries = helper.getLevel().registryAccess(); + for (var holder : server.getRecipeManager().getRecipes()) { + if (!holder.id().getNamespace().equals(ElectricAdvantage.MODID)) continue; + RegistryFriendlyByteBuf buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), registries); + try { + Recipe.STREAM_CODEC.encode(buffer, holder.value()); + var decoded = Recipe.STREAM_CODEC.decode(buffer); + helper.assertTrue(decoded.getSerializer() == holder.value().getSerializer() + && ItemStack.matches(decoded.getResultItem(registries), holder.value().getResultItem(registries)), + "Electric recipe changed over the native network codec: " + holder.id()); + } finally { + buffer.release(); + } + checked++; + } + helper.assertTrue(checked > 0, "No Electric recipes were present for the network check"); + helper.succeed(); + } + + @GameTest(batch = ElectricAdvantage.MODID, template = "empty") + public static void siliconAndSolderResolveRealMaterialTags(GameTestHelper helper) { + assertLoadedRecipe(helper, "silicon_blend", Items.silicon_blend, 1); + assertLoadedRecipe(helper, "silicon_ingot_from_blend", Items.silicon_ingot, 1); + assertLoadedRecipe(helper, "solder_blend_tin_lead", Items.solder_blend, 3); + assertLoadedRecipe(helper, "solder_blend_tin_silver", Items.solder_blend, 3); + assertLoadedRecipe(helper, "solder_from_blend", Items.solder, 1); + helper.succeed(); + } + + private static void assertLoadedRecipe(GameTestHelper helper, String path, Item item, int count) { + var id = ResourceLocation.fromNamespaceAndPath(ElectricAdvantage.MODID, path); + var level = helper.getLevel(); + var holder = level.getRecipeManager().byKey(id); + helper.assertTrue(holder.isPresent(), "Recipe was gated despite valid materials: " + id); + var recipe = holder.orElseThrow().value(); + helper.assertTrue(recipe.getIngredients().stream().allMatch(ingredient -> ingredient.getItems().length > 0), + "Recipe loaded with an empty ingredient: " + id); + helper.assertTrue(ItemStack.matches(new ItemStack(item, count), recipe.getResultItem(level.registryAccess())), + "Unexpected output for " + id); + } + + @GameTest(batch = ElectricAdvantage.MODID, template = "empty") + public static void turretUsesNativeUpdatePacket(GameTestHelper helper) { + BlockPos relative = new BlockPos(1, 1, 1); + helper.setBlock(relative, Blocks.laser_turret); + var turret = (LaserTurretTileEntity) helper.getBlockEntity(relative); + var packet = turret.getUpdatePacket(); + RegistryFriendlyByteBuf buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), helper.getLevel().registryAccess()); + try { + ClientboundBlockEntityDataPacket.STREAM_CODEC.encode(buffer, packet); + var decoded = ClientboundBlockEntityDataPacket.STREAM_CODEC.decode(buffer); + helper.assertTrue(decoded.getPos().equals(helper.absolutePos(relative)) + && decoded.getType() == turret.getType(), "The turret packet changed its native target"); + helper.assertTrue(decoded.getTag().contains("lock") && decoded.getTag().contains("energy"), + "The turret packet lost its render state"); + } finally { + buffer.release(); + } + helper.succeed(); + } +} diff --git a/src/gametest/resources/gameteststructures/empty.snbt b/src/gametest/resources/gameteststructures/empty.snbt new file mode 100644 index 0000000..bacaad7 --- /dev/null +++ b/src/gametest/resources/gameteststructures/empty.snbt @@ -0,0 +1 @@ +{DataVersion:3839,size:[3,3,3],palette:["minecraft:air"],data:[],entities:[]} diff --git a/src/main/java/zone/moddev/mc/baseelectric/ElectricAdvantage.java b/src/main/java/zone/moddev/mc/baseelectric/ElectricAdvantage.java index 23ad8ae..dfd89af 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/ElectricAdvantage.java +++ b/src/main/java/zone/moddev/mc/baseelectric/ElectricAdvantage.java @@ -25,13 +25,13 @@ import zone.moddev.mc.baseelectric.recipe.RecipeConditions; import zone.moddev.mc.baseelectric.migration.ElectricLegacyMigrations; -/** Forge 1.20.1 entry point for baseElectric. */ +/** Forge 1.20.6 entry point for baseElectric. */ @Mod(ElectricAdvantage.MODID) public final class ElectricAdvantage { public static final String MODID = "baseelectric"; public static final String LEGACY_MODID = "electricadvantage"; public static final String NAME = "baseElectric"; - public static final String VERSION = "2.2.13.120011"; + public static final String VERSION = "2.2.14.120061"; public static final Logger LOGGER = LogManager.getLogger(MODID); public static ElectricAdvantage INSTANCE; @@ -41,6 +41,7 @@ public final class ElectricAdvantage { public ElectricAdvantage(FMLJavaModLoadingContext context) { INSTANCE = this; ElectricLegacyMigrations.register(); + RecipeConditions.register(context.getModEventBus()); migrateLegacyOreSpawnConfiguration(); migrateLegacyConfiguration(); @@ -80,8 +81,6 @@ private static void migrateLegacyConfiguration() { private void commonSetup(FMLCommonSetupEvent event) { event.enqueueWork(GUI::init); - // CraftingHelper's shared condition map is not safe during parallel loading. - event.enqueueWork(RecipeConditions::register); ElectricAdvantageConfig.apply(); TreasureChests.init(FMLPaths.CONFIGDIR.get()); Villages.init(); diff --git a/src/main/java/zone/moddev/mc/baseelectric/compat/BaseMetalsCompat.java b/src/main/java/zone/moddev/mc/baseelectric/compat/BaseMetalsCompat.java index 8aaebae..1a0fe8e 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/compat/BaseMetalsCompat.java +++ b/src/main/java/zone/moddev/mc/baseelectric/compat/BaseMetalsCompat.java @@ -5,7 +5,7 @@ import net.minecraft.world.SimpleContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraftforge.fml.ModList; @@ -35,8 +35,8 @@ public static ItemStack getCrusherRecipeOutput(Level world, ItemStack input) { if (isLoaded()) { SimpleContainer inventory = new SimpleContainer(1); inventory.setItem(0, input.copy()); - for (Recipe candidate : world.getRecipeManager().getRecipes()) { - if (candidate instanceof CrushingRecipe && ((CrushingRecipe) candidate).matches(inventory, world)) { + for (RecipeHolder holder : world.getRecipeManager().getRecipes()) { + if (holder.value() instanceof CrushingRecipe candidate && candidate.matches(inventory, world)) { return candidate.getResultItem(world.registryAccess()).copy(); } } diff --git a/src/main/java/zone/moddev/mc/baseelectric/entities/HydroturbineEntity.java b/src/main/java/zone/moddev/mc/baseelectric/entities/HydroturbineEntity.java index 567fa98..e3447f9 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/entities/HydroturbineEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/entities/HydroturbineEntity.java @@ -7,9 +7,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.material.FluidState; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientGamePacketListener; -import net.minecraftforge.network.NetworkHooks; +import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; @@ -47,15 +45,10 @@ public HydroturbineEntity(Level w, BlockEntity parentTileEntity) { } @Override - protected void defineSynchedData() { + protected void defineSynchedData(SynchedEntityData.Builder builder) { // do nothing } - @Override - public Packet getAddEntityPacket() { - return NetworkHooks.getEntitySpawningPacket(this); - } - @Override public boolean isPushedByFluid() { // This is anchored to its generator; flow drives rotation, not linear movement. diff --git a/src/main/java/zone/moddev/mc/baseelectric/graphics/BufferedQuads.java b/src/main/java/zone/moddev/mc/baseelectric/graphics/BufferedQuads.java index 892bf69..16b689b 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/graphics/BufferedQuads.java +++ b/src/main/java/zone/moddev/mc/baseelectric/graphics/BufferedQuads.java @@ -53,7 +53,7 @@ void endVertex() { buffer.vertex(transform.pose(), vertex[0], vertex[1], vertex[2]) .color(255, 255, 255, 255).uv(vertex[3], vertex[4]) .overlayCoords(overlay).uv2(light) - .normal(transform.normal(), nx, ny, nz).endVertex(); + .normal(transform, nx, ny, nz).endVertex(); } count = 0; } diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/ArcFurnaceGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/ArcFurnaceGUI.java index 9719e02..660cabd 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/ArcFurnaceGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/ArcFurnaceGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -47,6 +50,7 @@ public void onTake(Player player, ItemStack stack) * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/BatteryArrayGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/BatteryArrayGUI.java index 024f4d3..bdad9e4 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/BatteryArrayGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/BatteryArrayGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricBatteryArrayTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -43,6 +46,7 @@ public BatteryArrayGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricBatteryArrayTileEntity){ ElectricBatteryArrayTileEntity te = (ElectricBatteryArrayTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricDrillGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricDrillGUI.java index 79d0eca..6d12521 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricDrillGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricDrillGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -34,6 +37,7 @@ public ElectricDrillGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricPumpGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricPumpGUI.java index ed5a9b3..b57643c 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricPumpGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricPumpGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricPumpTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -34,6 +37,7 @@ public ElectricPumpGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricPumpTileEntity){ ElectricPumpTileEntity te = (ElectricPumpTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricStillGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricStillGUI.java index 62bf2e1..2df9a6a 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricStillGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/ElectricStillGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricStillTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -34,6 +37,7 @@ public ElectricStillGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricStillTileEntity){ ElectricStillTileEntity te = (ElectricStillTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/FabricatorGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/FabricatorGUI.java index 31111c2..53110eb 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/FabricatorGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/FabricatorGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -56,6 +59,7 @@ public void onTake(Player player, ItemStack stack) * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/GUIHelper.java b/src/main/java/zone/moddev/mc/baseelectric/gui/GUIHelper.java index 1ae594a..27f9cb3 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/GUIHelper.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/GUIHelper.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import cyano.poweradvantage.api.simple.SimpleMachineGUI.GUIContainer; import zone.moddev.mc.basepower.gui.FluidTankGUI; @@ -24,12 +27,14 @@ public class GUIHelper { private static final Map realTextureLocationCache = new HashMap<>(); + @OnlyIn(Dist.CLIENT) public static void drawIndicatorLight(boolean on,GUIContainer gc, int xOffset, int yOffset){ if(on){ gc.blit(8+xOffset, 8+yOffset, INDICATOR_LED_X, INDICATOR_LED_Y, INDICATOR_LED_W, INDICATOR_LED_H); } } + @OnlyIn(Dist.CLIENT) public static void drawProgressBar(int x, int y, float progress, GUIContainer gc){ int w = progressBarWidth(progress); if(w == 0) return; @@ -43,6 +48,7 @@ static int progressBarWidth(float progress) { } + @OnlyIn(Dist.CLIENT) public static void drawFluidBar(FluidStack fs, float barHeight, int xPos, int yPos, GUIContainer guiContainer, int x, int y, float z, ResourceLocation displayImage){ diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/GenericMachineGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/GenericMachineGUI.java index 12eb0c0..788c6f8 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/GenericMachineGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/GenericMachineGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -32,6 +35,7 @@ public GenericMachineGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberControllerGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberControllerGUI.java index 91245d4..ab34ecf 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberControllerGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberControllerGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.GrowthChamberControllerTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -33,6 +36,7 @@ public GrowthChamberControllerGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof GrowthChamberControllerTileEntity){ GrowthChamberControllerTileEntity te = (GrowthChamberControllerTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberGUI.java index 50be1fe..9f31cba 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/GrowthChamberGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -34,6 +37,7 @@ public GrowthChamberGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/OvenGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/OvenGUI.java index 76cf1b4..ff7171b 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/OvenGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/OvenGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -46,6 +49,7 @@ public void onTake(Player player, ItemStack stack) * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/PlasticRefineryGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/PlasticRefineryGUI.java index 02f82ed..db2ee4d 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/PlasticRefineryGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/PlasticRefineryGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.PlasticRefineryTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -34,6 +37,7 @@ public PlasticRefineryGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof PlasticRefineryTileEntity){ PlasticRefineryTileEntity te = (PlasticRefineryTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/PowerGeneratorGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/PowerGeneratorGUI.java index 36301d8..a1a2a12 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/PowerGeneratorGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/PowerGeneratorGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricGeneratorTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -32,6 +35,7 @@ public PowerGeneratorGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricGeneratorTileEntity){ ElectricGeneratorTileEntity te = (ElectricGeneratorTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/gui/RockCrusherGUI.java b/src/main/java/zone/moddev/mc/baseelectric/gui/RockCrusherGUI.java index 4af31d6..b0e05c0 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/gui/RockCrusherGUI.java +++ b/src/main/java/zone/moddev/mc/baseelectric/gui/RockCrusherGUI.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.gui; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.baseelectric.machines.ElectricMachineTileEntity; import cyano.poweradvantage.api.simple.SimpleMachineGUI; @@ -34,6 +37,7 @@ public RockCrusherGUI() { * @param z This is the z coordinate (no units) into the depth of the screen */ @Override + @OnlyIn(Dist.CLIENT) public void drawGUIDecorations(Object srcEntity, GUIContainer guiContainer, int x, int y, float z){ if(srcEntity instanceof ElectricMachineTileEntity){ ElectricMachineTileEntity te = (ElectricMachineTileEntity)srcEntity; diff --git a/src/main/java/zone/moddev/mc/baseelectric/init/Villages.java b/src/main/java/zone/moddev/mc/baseelectric/init/Villages.java index 8017f94..6a60e31 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/init/Villages.java +++ b/src/main/java/zone/moddev/mc/baseelectric/init/Villages.java @@ -6,6 +6,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.MerchantOffer; +import net.minecraft.world.item.trading.ItemCost; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.village.VillagerTradesEvent; @@ -38,7 +39,7 @@ static VillagerTrades.ItemListing sell(Item item, int minimumPrice, int maximumP int price = minimumPrice + random.nextInt(maximumPrice - minimumPrice + 1); int emeralds = price < 0 ? 1 : price; int count = price < 0 ? -price : 1; - return new MerchantOffer(new ItemStack(net.minecraft.world.item.Items.EMERALD, emeralds), + return new MerchantOffer(new ItemCost(net.minecraft.world.item.Items.EMERALD, emeralds), new ItemStack(item, count), 7, 1, 0.0F); }; } diff --git a/src/main/java/zone/moddev/mc/baseelectric/items/BatteryItem.java b/src/main/java/zone/moddev/mc/baseelectric/items/BatteryItem.java index 4081eab..fe30fa2 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/items/BatteryItem.java +++ b/src/main/java/zone/moddev/mc/baseelectric/items/BatteryItem.java @@ -8,7 +8,9 @@ import net.minecraft.world.item.Item; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.world.level.Level; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.Tag; +import net.minecraft.world.item.component.CustomData; import java.text.NumberFormat; import java.util.List; @@ -28,30 +30,17 @@ public BatteryItem(float capacity, Item.Properties properties){ @Override public float getEnergy(ItemStack stack) { - if(stack.getItem() instanceof IRechargeableItem){ - BatteryItem battery = (BatteryItem)stack.getItem(); - CompoundTag dataTag; - if(!stack.hasTag()){ - return battery.capacity; // new battery starts with 100% charge - } else { - dataTag = stack.getTag(); - if(dataTag.contains("energy", 99)){ - return dataTag.getFloat("energy"); - } else { - return battery.capacity; // new battery starts with 100% charge - } - } - } else { - return 0; - } + if (!(stack.getItem() instanceof BatteryItem battery)) return 0; + // Vanilla moves unknown 1.20.1 item tags to CUSTOM_DATA on world upgrade. + CustomData data = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + if (!data.contains("energy")) return battery.capacity; + CompoundTag tag = data.copyTag(); + return tag.contains("energy", Tag.TAG_ANY_NUMERIC) ? tag.getFloat("energy") : battery.capacity; } @Override public void setEnergy(ItemStack stack, float energy){ if(stack.getItem() instanceof BatteryItem){ - CompoundTag dataTag; - dataTag = stack.getOrCreateTag(); - dataTag.putFloat("energy", energy); - stack.setTag(dataTag); + CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putFloat("energy", energy)); } } /** @@ -64,17 +53,9 @@ public void setEnergy(ItemStack stack, float energy){ public float addEnergy(ItemStack stack, float energy, ConduitType type){ if(ConduitType.areSameType(type, Power.ELECTRIC_POWER) && stack.getItem() instanceof BatteryItem){ BatteryItem battery = (BatteryItem)stack.getItem(); - CompoundTag dataTag; - dataTag = stack.getOrCreateTag(); - float currentEnergy; - if(dataTag.contains("energy", 99)){ - currentEnergy = dataTag.getFloat("energy"); - } else { - currentEnergy = battery.capacity; - } + float currentEnergy = getEnergy(stack); float newEnergy = Math.max(0, Math.min(currentEnergy+energy, battery.capacity)); - dataTag.putFloat("energy", newEnergy); - stack.setTag(dataTag); + setEnergy(stack, newEnergy); return newEnergy - currentEnergy; } else { return 0; @@ -93,8 +74,8 @@ public ConduitType getEnergyType(){ } @Override - public void appendHoverText(ItemStack stack, Level world, List list, TooltipFlag flag){ - super.appendHoverText(stack, world, list, flag); + public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag flag){ + super.appendHoverText(stack, context, list, flag); float max = getMaxEnergy(stack); if(max <= 0) return; // not a battery! float e = getEnergy(stack); diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillBlock.java b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillBlock.java index 6ce1326..28b2123 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillBlock.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillBlock.java @@ -12,6 +12,7 @@ import net.minecraft.world.Containers; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.ItemStack; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.StateDefinition; @@ -105,7 +106,7 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { @Override public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - if (stack.hasCustomHoverName()) { + if (stack.has(DataComponents.CUSTOM_NAME)) { BlockEntity tile = world.getBlockEntity(pos); if (tile instanceof PoweredEntity) { ((PoweredEntity) tile).setCustomInventoryName(stack.getHoverName().getString()); diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillTileEntity.java index 776aac5..8b56ea0 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricDrillTileEntity.java @@ -152,8 +152,8 @@ private boolean followTrack(){ BlockPos nextPos = getBlockPos().relative(trackDir); w.setBlock(nextPos, w.getBlockState(getBlockPos()), 2); ElectricDrillTileEntity te = (ElectricDrillTileEntity)w.getBlockEntity(nextPos); - CompoundTag dataTransfer = saveWithoutMetadata(); - te.load(dataTransfer); + CompoundTag dataTransfer = saveWithoutMetadata(w.registryAccess()); + te.loadWithComponents(dataTransfer, w.registryAccess()); te.clearRemoved(); te.subtractEnergy(ENERGY_COST_MOVE, getEnergyType()); te.setChanged(); @@ -289,7 +289,7 @@ public void onDataFieldUpdate() { pos.getX()+1,pos.getY()+1,pos.getZ()+1); List victims = getLevel().getEntitiesOfClass(LivingEntity.class, beamArea); for(Entity e : victims){ - e.setSecondsOnFire(3); + e.igniteForSeconds(3); e.hurt(Power.damageSource(getLevel(), Power.LASER_DAMAGE), 2f); } } @@ -457,7 +457,7 @@ private void inventoryTransfer(BlockPos adj, Direction otherFace) { inv.setChanged(); this.setChanged(); return; - } else if(ItemStack.isSameItemSameTags(theirItem, inventory[mySlot]) + } else if(ItemStack.isSameItemSameComponents(theirItem, inventory[mySlot]) && theirItem.getCount() < theirItem.getMaxStackSize() && theirItem.getCount() < inv.getMaxStackSize()){ theirItem.grow(1); @@ -546,7 +546,7 @@ public boolean isActive(){ @OnlyIn(Dist.CLIENT) public AABB getRenderBoundingBox() { - return new AABB(getBlockPos().offset(-renderRange, -renderRange, -renderRange), getBlockPos().offset(renderRange, renderRange, renderRange)); + return new AABB(getBlockPos()).inflate(renderRange); //return super.INFINITE_EXTENT_AABB; } } diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricGeneratorTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricGeneratorTileEntity.java index 6698dfa..2c20453 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricGeneratorTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricGeneratorTileEntity.java @@ -5,6 +5,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.item.ItemStack; import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.HolderLookup; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvent; @@ -162,14 +163,14 @@ public int getComparatorOutput(){ @Override - protected void saveAdditional(CompoundTag tagRoot){ - super.saveAdditional(tagRoot); + protected void saveAdditional(CompoundTag tagRoot, HolderLookup.Provider registries){ + super.saveAdditional(tagRoot, registries); saveTo(tagRoot); } @Override - public void load(CompoundTag tagRoot){ - super.load(tagRoot); + protected void loadAdditional(CompoundTag tagRoot, HolderLookup.Provider registries){ + super.loadAdditional(tagRoot, registries); loadFrom(tagRoot); } diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricMachineTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricMachineTileEntity.java index 689ddde..fcd24da 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricMachineTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricMachineTileEntity.java @@ -7,6 +7,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.HolderLookup; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.core.Direction; @@ -221,23 +222,23 @@ protected ItemStack getSmeltingResult(ItemStack input) { SimpleContainer inventory = new SimpleContainer(1); inventory.setItem(0, input); return getLevel().getRecipeManager().getRecipeFor(RecipeType.SMELTING, inventory, getLevel()) - .map(recipe -> recipe.assemble(inventory, getLevel().registryAccess())).orElse(ItemStack.EMPTY); + .map(recipe -> recipe.value().assemble(inventory, getLevel().registryAccess())).orElse(ItemStack.EMPTY); } @Override - protected void saveAdditional(CompoundTag tagRoot){ - super.saveAdditional(tagRoot); + protected void saveAdditional(CompoundTag tagRoot, HolderLookup.Provider registries){ + super.saveAdditional(tagRoot, registries); saveTo(tagRoot); } @Override - public CompoundTag getUpdateTag() { - return saveWithoutMetadata(); + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + return saveWithoutMetadata(registries); } @Override - public void load(CompoundTag tagRoot){ - super.load(tagRoot); + protected void loadAdditional(CompoundTag tagRoot, HolderLookup.Provider registries){ + super.loadAdditional(tagRoot, registries); loadFrom(tagRoot); } diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricOvenTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricOvenTileEntity.java index 439f403..f461667 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricOvenTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricOvenTileEntity.java @@ -2,7 +2,7 @@ import zone.moddev.mc.baseelectric.init.Power; import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.item.Item; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.item.ItemStack; import net.minecraft.nbt.CompoundTag; @@ -51,8 +51,7 @@ public void tickUpdate(boolean isServerWorld) { public static boolean isFoodItem(ItemStack item){ if(item == null) return false; - Item i = item.getItem(); - return !item.isEmpty() && i.isEdible(); + return !item.isEmpty() && item.has(DataComponents.FOOD); } public boolean becomesFoodItem(ItemStack item){ diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricPumpTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricPumpTileEntity.java index 066961b..a1b91b8 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricPumpTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/ElectricPumpTileEntity.java @@ -86,7 +86,7 @@ public void tickUpdate(boolean isServerWorld) { if(blockstate.getBlock() instanceof BucketPickup && getEnergy() >= cost){ // Native pickup drains waterlogging without deleting the containing block. Fluid f = blockstate.getFluidState().getType(); - ItemStack pickup = ((BucketPickup)blockstate.getBlock()).pickupBlock(w, fluidSource, blockstate); + ItemStack pickup = ((BucketPickup)blockstate.getBlock()).pickupBlock(null, w, fluidSource, blockstate); if(pickup != null && !pickup.isEmpty() && f != net.minecraft.world.level.material.Fluids.EMPTY){ this.getTank().fill(new FluidStack(f, FluidTank.BUCKET_VOLUME), true); this.subtractEnergy(cost, Power.ELECTRIC_POWER); diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/GrowthChamberControllerTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/GrowthChamberControllerTileEntity.java index 4dd324e..6355187 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/GrowthChamberControllerTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/GrowthChamberControllerTileEntity.java @@ -11,6 +11,7 @@ import zone.moddev.mc.basepower.init.Fluids; import net.minecraft.world.item.ItemStack; import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.HolderLookup; import net.minecraft.core.Direction; import net.minecraft.world.level.material.Fluid; import cyano.poweradvantage.api.fluid.FluidStack; @@ -193,8 +194,8 @@ public void onDataFieldUpdate() { * @param tagRoot An NBT tag */ @Override - protected void saveAdditional(final CompoundTag tagRoot) { - super.saveAdditional(tagRoot); + protected void saveAdditional(final CompoundTag tagRoot, HolderLookup.Provider registries) { + super.saveAdditional(tagRoot, registries); CompoundTag tankTag = new CompoundTag(); this.getTank().writeToNBT(tankTag); tagRoot.put("Tank", tankTag); @@ -205,8 +206,8 @@ protected void saveAdditional(final CompoundTag tagRoot) { * @param tagRoot An NBT tag */ @Override - public void load(final CompoundTag tagRoot) { - super.load(tagRoot); + protected void loadAdditional(final CompoundTag tagRoot, HolderLookup.Provider registries) { + super.loadAdditional(tagRoot, registries); if (tagRoot.contains("Tank", 10)) { CompoundTag tankTag = tagRoot.getCompound("Tank"); getTank().readFromNBT(tankTag); diff --git a/src/main/java/zone/moddev/mc/baseelectric/machines/LaserTurretTileEntity.java b/src/main/java/zone/moddev/mc/baseelectric/machines/LaserTurretTileEntity.java index 51162b2..39ca20f 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/machines/LaserTurretTileEntity.java +++ b/src/main/java/zone/moddev/mc/baseelectric/machines/LaserTurretTileEntity.java @@ -12,6 +12,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.world.item.ItemStack; import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.HolderLookup; import net.minecraft.network.Connection; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.scores.Team; @@ -25,6 +26,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; @@ -272,7 +274,7 @@ && rayIntersectsBoundingBox(origin,dir,v.getBoundingBox())){ private void hurtVictim(Entity e){ - e.setSecondsOnFire(BURN_TIME); + e.igniteForSeconds(BURN_TIME); if(e instanceof LivingEntity){ ((LivingEntity)e).hurt(Power.damageSource(getLevel(), Power.LASER_DAMAGE), ATTACK_DAMAGE); BlockPos bp = e.blockPosition(); @@ -304,7 +306,7 @@ private Vec3 calculateLaserTerminus(){ private Vec3 followRayToSolidBlock(Vec3 origin, Vec3 dir, double maxRange){ Vec3 max = origin.add(maxRange * dir.x, maxRange * dir.y, maxRange * dir.z); BlockHitResult impact = getLevel().clip(new ClipContext(origin, max, - ClipContext.Block.COLLIDER, ClipContext.Fluid.SOURCE_ONLY, null) { + ClipContext.Block.COLLIDER, ClipContext.Fluid.SOURCE_ONLY, CollisionContext.empty()) { @Override public VoxelShape getBlockShape(BlockState state, BlockGetter world, BlockPos pos) { // The optic is inside our collision post; ignore only this block, not nearby cover. return pos.equals(LaserTurretTileEntity.this.getBlockPos()) ? Shapes.empty() @@ -394,7 +396,7 @@ public boolean canSeeEntity(Entity e){ Vec3 offsetOrigin = getOpticPosition().add(e.position().subtract(getOpticPosition()).normalize()); BlockHitResult collision = getLevel().clip(new ClipContext(offsetOrigin, e.position().add(0, e.getBbHeight()*0.5, 0), ClipContext.Block.COLLIDER, - ClipContext.Fluid.SOURCE_ONLY, null)); + ClipContext.Fluid.SOURCE_ONLY, CollisionContext.empty())); if(collision.getType() == HitResult.Type.BLOCK){ return false; } @@ -496,7 +498,8 @@ private void storeOld(){ */ @Override public ClientboundBlockEntityDataPacket getUpdatePacket(){ - return ClientboundBlockEntityDataPacket.create(this, tile -> { + if (getLevel() == null) return null; + return ClientboundBlockEntityDataPacket.create(this, (tile, registries) -> { CompoundTag tag = new CompoundTag(); writeRenderSync(tag); return tag; @@ -504,15 +507,15 @@ public ClientboundBlockEntityDataPacket getUpdatePacket(){ } @Override - public CompoundTag getUpdateTag() { - CompoundTag nbtTag = super.getUpdateTag(); + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + CompoundTag nbtTag = super.getUpdateTag(registries); writeRenderSync(nbtTag); return nbtTag; } @Override - public void handleUpdateTag(CompoundTag tag) { - load(tag); + public void handleUpdateTag(CompoundTag tag, HolderLookup.Provider registries) { + super.handleUpdateTag(tag, registries); readRenderSync(tag); } @@ -537,7 +540,7 @@ private void writeRenderSync(CompoundTag nbtTag) { * Receives the network packet made by getDescriptionPacket() */ @Override - public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket packet) { + public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket packet, HolderLookup.Provider registries) { readRenderSync(packet.getTag()); } @@ -654,6 +657,6 @@ public int getComparatorOutput(){ @OnlyIn(Dist.CLIENT) public AABB getRenderBoundingBox() { - return new AABB(getBlockPos().offset(-renderRange, -renderRange, -renderRange), getBlockPos().offset(renderRange, renderRange, renderRange)); + return new AABB(getBlockPos()).inflate(renderRange); } } diff --git a/src/main/java/zone/moddev/mc/baseelectric/recipe/RecipeConditions.java b/src/main/java/zone/moddev/mc/baseelectric/recipe/RecipeConditions.java index 391822b..93e92c9 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/recipe/RecipeConditions.java +++ b/src/main/java/zone/moddev/mc/baseelectric/recipe/RecipeConditions.java @@ -1,68 +1,56 @@ package zone.moddev.mc.baseelectric.recipe; import java.util.Locale; -import com.google.gson.JsonObject; -import net.minecraft.util.GsonHelper; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.CraftingHelper; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.MapCodec; import net.minecraftforge.common.crafting.conditions.ICondition; -import net.minecraftforge.common.crafting.conditions.IConditionSerializer; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; import zone.moddev.mc.baseelectric.ElectricAdvantage; import zone.moddev.mc.basepower.PowerAdvantage; import zone.moddev.mc.basepower.RecipeMode; -/** Registers the data-pack conditions used by ElectricAdvantage recipes. */ +/** Registers the data-pack conditions used by Electric Advantage recipes. */ public final class RecipeConditions { - private static boolean registered; - private RecipeConditions() {} - - public static synchronized void register() { - if (registered) return; - CraftingHelper.register(new ModeSerializer(false)); - CraftingHelper.register(new ModeSerializer(true)); - registered = true; + private static final DeferredRegister> SERIALIZERS = + DeferredRegister.create(ForgeRegistries.Keys.CONDITION_SERIALIZERS, ElectricAdvantage.MODID); + private static final Codec MODE = Codec.STRING.comapFlatMap( + name -> { + try { + return DataResult.success(RecipeMode.valueOf(name.toUpperCase(Locale.ROOT))); + } catch (IllegalArgumentException ex) { + return DataResult.error(() -> "Unknown baseElectric recipe mode: " + name); + } + }, + mode -> mode.name().toLowerCase(Locale.ROOT)); + static final MapCodec MATCH = modeCodec(false); + static final MapCodec NOT_MATCH = modeCodec(true); + + static { + SERIALIZERS.register("recipe_mode", () -> MATCH); + SERIALIZERS.register("not_recipe_mode", () -> NOT_MATCH); } - static final class ModeCondition implements ICondition { - private final RecipeMode mode; - private final boolean inverted; - - ModeCondition(RecipeMode mode, boolean inverted) { - this.mode = mode; - this.inverted = inverted; - } - - @Override public ResourceLocation getID() { - return new ResourceLocation(ElectricAdvantage.MODID, - inverted ? "not_recipe_mode" : "recipe_mode"); - } - - public boolean test() { return test(IContext.EMPTY); } + private RecipeConditions() {} - @Override public boolean test(IContext context) { - return (PowerAdvantage.recipeMode == mode) != inverted; - } + public static void register(IEventBus bus) { + SERIALIZERS.register(bus); } - static final class ModeSerializer implements IConditionSerializer { - private final boolean inverted; - - ModeSerializer(boolean inverted) { - this.inverted = inverted; - } - - @Override public void write(JsonObject json, ModeCondition condition) { - json.addProperty("mode", condition.mode.name().toLowerCase(Locale.ROOT)); - } + private static MapCodec modeCodec(boolean inverted) { + return MODE.fieldOf("mode").xmap(mode -> new ModeCondition(mode, inverted), ModeCondition::mode); + } - @Override public ModeCondition read(JsonObject json) { - return new ModeCondition(RecipeMode.valueOf( - GsonHelper.getAsString(json, "mode").toUpperCase(Locale.ROOT)), inverted); + record ModeCondition(RecipeMode mode, boolean inverted) implements ICondition { + @Override public boolean test(IContext context, DynamicOps ops) { + return (PowerAdvantage.recipeMode == mode) != inverted; } - @Override public ResourceLocation getID() { - return new ResourceLocation(ElectricAdvantage.MODID, - inverted ? "not_recipe_mode" : "recipe_mode"); + @Override public MapCodec codec() { + return inverted ? NOT_MATCH : MATCH; } } } diff --git a/src/main/java/zone/moddev/mc/baseelectric/util/crafting/RecipeDeconstructor.java b/src/main/java/zone/moddev/mc/baseelectric/util/crafting/RecipeDeconstructor.java index 70ffec2..9b0c8d3 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/util/crafting/RecipeDeconstructor.java +++ b/src/main/java/zone/moddev/mc/baseelectric/util/crafting/RecipeDeconstructor.java @@ -10,6 +10,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; import zone.moddev.mc.baseelectric.ElectricAdvantage; @@ -34,10 +35,11 @@ public void invalidateRecipeCache() { } private void initializeRecipeCache(Level world) { - Collection> recipes = world.getRecipeManager().getRecipes(); + Collection> recipes = world.getRecipeManager().getRecipes(); if (cachedRecipeCount == recipes.size() && !recipeCache.isEmpty()) return; recipeCache.clear(); - for (Recipe recipe : recipes) { + for (RecipeHolder holder : recipes) { + Recipe recipe = holder.value(); ItemStack output = recipe.getResultItem(world.registryAccess()); if (output == null || output.isEmpty()) continue; recipeCache.computeIfAbsent(new ItemRecord(output), ignored -> new ArrayList<>()).add(recipe); diff --git a/src/main/java/zone/moddev/mc/baseelectric/util/farming/VirtualCrop.java b/src/main/java/zone/moddev/mc/baseelectric/util/farming/VirtualCrop.java index 61b601f..df866b9 100644 --- a/src/main/java/zone/moddev/mc/baseelectric/util/farming/VirtualCrop.java +++ b/src/main/java/zone/moddev/mc/baseelectric/util/farming/VirtualCrop.java @@ -1,5 +1,8 @@ package zone.moddev.mc.baseelectric.util.farming; +import com.mojang.serialization.JsonOps; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; import zone.moddev.mc.baseelectric.util.crafting.ItemRecord; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.StemBlock; @@ -63,8 +66,8 @@ public static VirtualCrop createVirtualCrop(ItemStack stack, Level w, BlockPos p BlockState startingState = plantable.getPlant(w, pos); Block block = startingState.getBlock(); int numStages = getNumberOfGrowthStages(startingState); - if(block instanceof StemBlock){ - Block product = ((StemBlock)block).getFruit(); + if(block instanceof StemBlock stem){ + Block product = resolveStemFruit(stem, w); if(product == null) { return null; } @@ -80,6 +83,16 @@ public static VirtualCrop createVirtualCrop(ItemStack stack, Level w, BlockPos p } + private static Block resolveStemFruit(StemBlock stem, Level world) { + // Forge 50 exposes the registered fruit key through the native stem codec. + var ops = world.registryAccess().createSerializationContext(JsonOps.INSTANCE); + return StemBlock.CODEC.codec().encodeStart(ops, stem).result() + .flatMap(data -> ResourceKey.codec(Registries.BLOCK) + .parse(ops, data.getAsJsonObject().get("fruit")).result()) + .map(key -> world.registryAccess().registryOrThrow(Registries.BLOCK).get(key)) + .orElse(null); + } + public VirtualCrop copy(){ return new VirtualCrop(this.prematureHarvest,this.numberOfStages, this.harvest); } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 111623b..c9da2eb 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -30,13 +30,13 @@ side="BOTH" [[dependencies.baseelectric]] modId="basepower" mandatory=true -versionRange="[2.4.12.120011,3.0.0)" +versionRange="[2.4.13.120061,3.0.0)" ordering="AFTER" side="BOTH" [[dependencies.baseelectric]] modId="basemetals" mandatory=false -versionRange="[3.1.2.120011,4.0.0)" +versionRange="[3.1.2.120061,4.0.0)" ordering="AFTER" side="BOTH" diff --git a/src/main/resources/assets/baseelectric/shaders/core/unshaded.json b/src/main/resources/assets/baseelectric/shaders/core/unshaded.json index 8ef3e67..5969f9b 100644 --- a/src/main/resources/assets/baseelectric/shaders/core/unshaded.json +++ b/src/main/resources/assets/baseelectric/shaders/core/unshaded.json @@ -7,7 +7,6 @@ "uniforms": [ {"name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}, {"name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}, - {"name": "IViewRotMat", "type": "matrix3x3", "count": 9, "values": [1,0,0,0,1,0,0,0,1]}, {"name": "ColorModulator", "type": "float", "count": 4, "values": [1,1,1,1]}, {"name": "FogStart", "type": "float", "count": 1, "values": [0]}, {"name": "FogEnd", "type": "float", "count": 1, "values": [1]}, diff --git a/src/main/resources/assets/baseelectric/shaders/core/unshaded.vsh b/src/main/resources/assets/baseelectric/shaders/core/unshaded.vsh index 0f53d7a..4697e71 100644 --- a/src/main/resources/assets/baseelectric/shaders/core/unshaded.vsh +++ b/src/main/resources/assets/baseelectric/shaders/core/unshaded.vsh @@ -13,7 +13,6 @@ uniform sampler2D Sampler1; uniform sampler2D Sampler2; uniform mat4 ModelViewMat; uniform mat4 ProjMat; -uniform mat3 IViewRotMat; uniform int FogShape; out float vertexDistance; @@ -21,15 +20,13 @@ out vec4 vertexColor; out vec4 lightMapColor; out vec4 overlayColor; out vec2 texCoord0; -out vec4 normal; void main() { vec4 viewPosition = ModelViewMat * vec4(Position, 1.0); gl_Position = ProjMat * viewPosition; - vertexDistance = fog_distance(ModelViewMat, IViewRotMat * Position, FogShape); + vertexDistance = fog_distance(Position, FogShape); vertexColor = Color; lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); overlayColor = texelFetch(Sampler1, UV1, 0); texCoord0 = UV0; - normal = ProjMat * ModelViewMat * vec4(Normal, 0.0); } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/alkaline_battery.json b/src/main/resources/data/baseelectric/advancements/recipes/alkaline_battery.json index 701c715..50cd770 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/alkaline_battery.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/alkaline_battery.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/iron" + "items": "#forge:ingots/iron" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/zinc" + "items": "#forge:ingots/zinc" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_ingot_normal.json b/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_ingot_normal.json index c22123c..1944125 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_ingot_normal.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_ingot_normal.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/copper" + "items": "#forge:ingots/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_plate.json b/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_plate.json index 91e5294..fa84ef3 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_plate.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/blank_circuit_board_plate.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/copper" + "items": "#forge:plates/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/control_circuit.json b/src/main/resources/data/baseelectric/advancements/recipes/control_circuit.json index 7ef96a1..3246e7a 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/control_circuit.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/control_circuit.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:microchips" + "items": "#forge:microchips" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:solder" + "items": "#forge:solder" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_battery_array.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_battery_array.json index e183022..c268937 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_battery_array.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_battery_array.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_ingot.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_ingot.json index 81136f5..5da3c19 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_ingot.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_ingot.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/copper" + "items": "#forge:ingots/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_rod.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_rod.json index 6152022..218ac1c 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_rod.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_plastic_rod.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:rods/copper" + "items": "#forge:rods/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_ingot.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_ingot.json index ac4e96c..f919bcb 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_ingot.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_ingot.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:rubber" + "items": "#forge:rubber" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/copper" + "items": "#forge:ingots/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_rod.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_rod.json index 56f16dc..f5c9871 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_rod.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_conduit_rubber_rod.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:rubber" + "items": "#forge:rubber" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:rods/copper" + "items": "#forge:rods/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_crusher.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_crusher.json index 705c2c3..1b8b5ad 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_crusher.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_crusher.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:sprockets" + "items": "#forge:sprockets" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:gems/diamond" + "items": "#forge:gems/diamond" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -46,7 +46,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_drill.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_drill.json index 05b5746..9ee8057 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_drill.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_drill.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:storage_blocks/diamond" + "items": "#forge:storage_blocks/diamond" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_fabricator.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_fabricator.json index 0b70fa3..74935fc 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_fabricator.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_fabricator.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_furnace.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_furnace.json index 011a630..3775ea8 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_furnace.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_furnace.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_oven.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_oven.json index 0257ce6..61f9b10 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_oven.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_oven.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:glass_panes" + "items": "#forge:glass_panes" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_pump.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_pump.json index 8aef1cd..a698ccb 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_pump.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_pump.json @@ -30,7 +30,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -40,7 +40,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -50,7 +50,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_still.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_still.json index 972b14f..fda26f1 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_still.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_still.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/electric_switch.json b/src/main/resources/data/baseelectric/advancements/recipes/electric_switch.json index f454146..5ef33ae 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/electric_switch.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/electric_switch.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber.json b/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber.json index fadd6b5..53f7bcc 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:microchips" + "items": "#forge:microchips" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -48,7 +48,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber_controller.json b/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber_controller.json index fbd4030..6231a0b 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber_controller.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/growth_chamber_controller.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:circuit_boards" + "items": "#forge:circuit_boards" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -48,7 +48,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/hydroelectric_generator.json b/src/main/resources/data/baseelectric/advancements/recipes/hydroelectric_generator.json index bcd7b35..13131da 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/hydroelectric_generator.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/hydroelectric_generator.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:sprockets" + "items": "#forge:sprockets" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_normal.json b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_normal.json index 600d50a..9f10b69 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_normal.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_normal.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/copper" + "items": "#forge:nuggets/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_tech.json b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_tech.json index f66ada2..9aedbaa 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_tech.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_copper_tech.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/redstone" + "items": "#forge:dusts/redstone" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/copper" + "items": "#forge:nuggets/copper" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_normal.json b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_normal.json index dada91a..08aad0d 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_normal.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_normal.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/gold" + "items": "#forge:nuggets/gold" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_tech.json b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_tech.json index f4e7a4c..5fc47a8 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_tech.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_gold_tech.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/redstone" + "items": "#forge:dusts/redstone" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/gold" + "items": "#forge:nuggets/gold" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_normal.json b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_normal.json index c453c4c..2dd5672 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_normal.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_normal.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/tin" + "items": "#forge:nuggets/tin" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_tech.json b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_tech.json index a8986dd..87922cf 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_tech.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/integrated_circuit_tin_tech.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/redstone" + "items": "#forge:dusts/redstone" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/tin" + "items": "#forge:nuggets/tin" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_diamond_emerald.json b/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_diamond_emerald.json index 4561af3..f33f065 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_diamond_emerald.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_diamond_emerald.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:gems/diamond" + "items": "#forge:gems/diamond" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:gems/emerald" + "items": "#forge:gems/emerald" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -46,7 +46,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_emerald_diamond.json b/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_emerald_diamond.json index e85fbf7..5dd4708 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_emerald_diamond.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/laser_turret_emerald_diamond.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:gems/emerald" + "items": "#forge:gems/emerald" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:gems/diamond" + "items": "#forge:gems/diamond" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -46,7 +46,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_dust_sulfur.json b/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_dust_sulfur.json index fc6b4a6..8b758c7 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_dust_sulfur.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_dust_sulfur.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/lead" + "items": "#forge:ingots/lead" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/sulfur" + "items": "#forge:dusts/sulfur" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_sulfur.json b/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_sulfur.json index 1e985ff..9673935 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_sulfur.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/lead_acid_battery_sulfur.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/lead" + "items": "#forge:ingots/lead" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:sulfur" + "items": "#forge:sulfur" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/led_bar.json b/src/main/resources/data/baseelectric/advancements/recipes/led_bar.json index 2eeb86f..1169fce 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/led_bar.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/led_bar.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:glass_panes" + "items": "#forge:glass_panes" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:microchips" + "items": "#forge:microchips" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/lithium_battery.json b/src/main/resources/data/baseelectric/advancements/recipes/lithium_battery.json index 8a449ca..8f55ca5 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/lithium_battery.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/lithium_battery.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/lithium" + "items": "#forge:ingots/lithium" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/redstone" + "items": "#forge:dusts/redstone" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/carbon" + "items": "#forge:dusts/carbon" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/lithium_ingot_from_nuggets.json b/src/main/resources/data/baseelectric/advancements/recipes/lithium_ingot_from_nuggets.json index 044e5f5..27389ad 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/lithium_ingot_from_nuggets.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/lithium_ingot_from_nuggets.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:nuggets/lithium" + "items": "#forge:nuggets/lithium" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/lithium_nuggets.json b/src/main/resources/data/baseelectric/advancements/recipes/lithium_nuggets.json index 4cb6996..fc4fd0a 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/lithium_nuggets.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/lithium_nuggets.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/lithium" + "items": "#forge:ingots/lithium" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/nickel_hydride_battery.json b/src/main/resources/data/baseelectric/advancements/recipes/nickel_hydride_battery.json index 10bcc13..00bad79 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/nickel_hydride_battery.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/nickel_hydride_battery.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/nickel" + "items": "#forge:ingots/nickel" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/redstone" + "items": "#forge:dusts/redstone" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plastic" + "items": "#forge:plastic" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/photovoltaic_generator.json b/src/main/resources/data/baseelectric/advancements/recipes/photovoltaic_generator.json index 818e45b..f6a4e35 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/photovoltaic_generator.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/photovoltaic_generator.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:glass_panes" + "items": "#forge:glass_panes" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/silicon" + "items": "#forge:ingots/silicon" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/plastic_refinery.json b/src/main/resources/data/baseelectric/advancements/recipes/plastic_refinery.json index a1593c2..c129da6 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/plastic_refinery.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/plastic_refinery.json @@ -18,7 +18,7 @@ "conditions": { "items": [ { - "tag": "forge:sprockets" + "items": "#forge:sprockets" } ] } @@ -28,7 +28,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -38,7 +38,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -48,7 +48,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_iron_normal.json b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_iron_normal.json index 4e0cfaa..f6d448d 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_iron_normal.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_iron_normal.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:circuit_boards" + "items": "#forge:circuit_boards" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/iron" + "items": "#forge:ingots/iron" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_apocalyptic.json b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_apocalyptic.json index a92fbf9..cb95662 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_apocalyptic.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_apocalyptic.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:circuit_boards" + "items": "#forge:circuit_boards" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_tech.json b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_tech.json index 661ed46..bda60e1 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_tech.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_plate_steel_tech.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:circuit_boards" + "items": "#forge:circuit_boards" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_steel_normal.json b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_steel_normal.json index 47b79d3..c748d4e 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_steel_normal.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/power_supply_unit_steel_normal.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:wires" + "items": "#forge:wires" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:circuit_boards" + "items": "#forge:circuit_boards" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:ingots/steel" + "items": "#forge:ingots/steel" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/silicon_blend.json b/src/main/resources/data/baseelectric/advancements/recipes/silicon_blend.json index 4029923..1517fcb 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/silicon_blend.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/silicon_blend.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:sand" + "items": "#forge:sand" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/carbon" + "items": "#forge:dusts/carbon" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_lead.json b/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_lead.json index c1eaa7c..042071a 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_lead.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_lead.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/tin" + "items": "#forge:dusts/tin" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/lead" + "items": "#forge:dusts/lead" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_silver.json b/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_silver.json index eafbf22..1913038 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_silver.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/solder_blend_tin_silver.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/tin" + "items": "#forge:dusts/tin" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:dusts/silver" + "items": "#forge:dusts/silver" } ] } diff --git a/src/main/resources/data/baseelectric/advancements/recipes/steam_powered_generator.json b/src/main/resources/data/baseelectric/advancements/recipes/steam_powered_generator.json index 6081d96..06c07dd 100644 --- a/src/main/resources/data/baseelectric/advancements/recipes/steam_powered_generator.json +++ b/src/main/resources/data/baseelectric/advancements/recipes/steam_powered_generator.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "forge:conduits/steam" + "items": "#forge:conduits/steam" } ] } @@ -16,7 +16,7 @@ "conditions": { "items": [ { - "tag": "forge:governors" + "items": "#forge:governors" } ] } @@ -26,7 +26,7 @@ "conditions": { "items": [ { - "tag": "forge:power_supply_units" + "items": "#forge:power_supply_units" } ] } @@ -36,7 +36,7 @@ "conditions": { "items": [ { - "tag": "forge:plates/steel" + "items": "#forge:plates/steel" } ] } @@ -46,7 +46,7 @@ "conditions": { "items": [ { - "tag": "forge:frames/steel" + "items": "#forge:frames/steel" } ] } diff --git a/src/main/resources/data/baseelectric/recipes/alkaline_battery.json b/src/main/resources/data/baseelectric/recipes/alkaline_battery.json index c3e8985..045ddc9 100644 --- a/src/main/resources/data/baseelectric/recipes/alkaline_battery.json +++ b/src/main/resources/data/baseelectric/recipes/alkaline_battery.json @@ -20,21 +20,24 @@ } }, "result": { - "item": "baseelectric:alkaline_battery" + "id": "baseelectric:alkaline_battery" }, "group": "baseelectric:alkaline_battery", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/iron" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/zinc" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/iron" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/zinc" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/blank_circuit_board_ingot_normal.json b/src/main/resources/data/baseelectric/recipes/blank_circuit_board_ingot_normal.json index 5853396..56c4bf1 100644 --- a/src/main/resources/data/baseelectric/recipes/blank_circuit_board_ingot_normal.json +++ b/src/main/resources/data/baseelectric/recipes/blank_circuit_board_ingot_normal.json @@ -9,22 +9,25 @@ } ], "result": { - "item": "baseelectric:blank_circuit_board", + "id": "baseelectric:blank_circuit_board", "count": 2 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "NORMAL" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/copper" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ], - "group": "baseelectric:blank_circuit_board" + "group": "baseelectric:blank_circuit_board", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "NORMAL" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/copper" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/blank_circuit_board_plate.json b/src/main/resources/data/baseelectric/recipes/blank_circuit_board_plate.json index 924834d..e4c7c94 100644 --- a/src/main/resources/data/baseelectric/recipes/blank_circuit_board_plate.json +++ b/src/main/resources/data/baseelectric/recipes/blank_circuit_board_plate.json @@ -9,18 +9,21 @@ } ], "result": { - "item": "baseelectric:blank_circuit_board", + "id": "baseelectric:blank_circuit_board", "count": 2 }, "group": "baseelectric:blank_circuit_board", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/copper" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/copper" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/control_circuit.json b/src/main/resources/data/baseelectric/recipes/control_circuit.json index c5a2557..f4cb8bb 100644 --- a/src/main/resources/data/baseelectric/recipes/control_circuit.json +++ b/src/main/resources/data/baseelectric/recipes/control_circuit.json @@ -12,17 +12,20 @@ } ], "result": { - "item": "baseelectric:control_circuit" + "id": "baseelectric:control_circuit" }, "group": "baseelectric:control_circuit", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:microchips" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:solder" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:microchips" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:solder" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_control_circuit.json b/src/main/resources/data/baseelectric/recipes/crushing_control_circuit.json index 2aba934..5d73a79 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_control_circuit.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_control_circuit.json @@ -4,17 +4,20 @@ "item": "baseelectric:control_circuit" }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 1 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "baseelectric:recipe_mode", - "mode": "APOCALYPTIC" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "baseelectric:recipe_mode", + "mode": "APOCALYPTIC" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_electric_furnace.json b/src/main/resources/data/baseelectric/recipes/crushing_electric_furnace.json index b29f0ee..a83beb1 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_electric_furnace.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_electric_furnace.json @@ -4,17 +4,20 @@ "item": "baseelectric:electric_furnace" }, "result": { - "item": "baseelectric:psu", + "id": "baseelectric:psu", "count": 1 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "baseelectric:recipe_mode", - "mode": "APOCALYPTIC" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "baseelectric:recipe_mode", + "mode": "APOCALYPTIC" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_lithium_ingot.json b/src/main/resources/data/baseelectric/recipes/crushing_lithium_ingot.json index eac6eff..82ae9a6 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_lithium_ingot.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_lithium_ingot.json @@ -4,17 +4,20 @@ "tag": "forge:ingots/lithium" }, "result": { - "item": "baseelectric:li_powder", + "id": "baseelectric:li_powder", "count": 1 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/lithium" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/lithium" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_lithium_ore.json b/src/main/resources/data/baseelectric/recipes/crushing_lithium_ore.json index de3bfc9..0dede26 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_lithium_ore.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_lithium_ore.json @@ -4,17 +4,20 @@ "tag": "forge:ores/lithium" }, "result": { - "item": "baseelectric:li_powder", + "id": "baseelectric:li_powder", "count": 2 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ores/lithium" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ores/lithium" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_photovoltaic_generator.json b/src/main/resources/data/baseelectric/recipes/crushing_photovoltaic_generator.json index 3fd4852..202591b 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_photovoltaic_generator.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_photovoltaic_generator.json @@ -4,17 +4,20 @@ "item": "baseelectric:photovoltaic_generator" }, "result": { - "item": "baseelectric:psu", + "id": "baseelectric:psu", "count": 1 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "baseelectric:recipe_mode", - "mode": "APOCALYPTIC" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "baseelectric:recipe_mode", + "mode": "APOCALYPTIC" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_psu.json b/src/main/resources/data/baseelectric/recipes/crushing_psu.json index 289c1ed..d19f676 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_psu.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_psu.json @@ -4,17 +4,20 @@ "item": "baseelectric:psu" }, "result": { - "item": "baseelectric:control_circuit", + "id": "baseelectric:control_circuit", "count": 1 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "baseelectric:recipe_mode", - "mode": "APOCALYPTIC" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "baseelectric:recipe_mode", + "mode": "APOCALYPTIC" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_steam_powered_generator.json b/src/main/resources/data/baseelectric/recipes/crushing_steam_powered_generator.json index 9f6db76..83aacd7 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_steam_powered_generator.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_steam_powered_generator.json @@ -4,17 +4,20 @@ "item": "baseelectric:steam_powered_generator" }, "result": { - "item": "baseelectric:psu", + "id": "baseelectric:psu", "count": 1 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "baseelectric:recipe_mode", - "mode": "APOCALYPTIC" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "baseelectric:recipe_mode", + "mode": "APOCALYPTIC" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/crushing_sulfur_ore.json b/src/main/resources/data/baseelectric/recipes/crushing_sulfur_ore.json index 6828fdb..828f9ad 100644 --- a/src/main/resources/data/baseelectric/recipes/crushing_sulfur_ore.json +++ b/src/main/resources/data/baseelectric/recipes/crushing_sulfur_ore.json @@ -4,17 +4,20 @@ "tag": "forge:ores/sulfur" }, "result": { - "item": "baseelectric:sulfur_powder", + "id": "baseelectric:sulfur_powder", "count": 4 }, - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "basemetals" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ores/sulfur" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "forge:mod_loaded", + "modid": "basemetals" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ores/sulfur" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_battery_array.json b/src/main/resources/data/baseelectric/recipes/electric_battery_array.json index c7f5733..519c09c 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_battery_array.json +++ b/src/main/resources/data/baseelectric/recipes/electric_battery_array.json @@ -19,21 +19,24 @@ } }, "result": { - "item": "baseelectric:electric_battery_array" + "id": "baseelectric:electric_battery_array" }, "group": "baseelectric:electric_battery_array", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_ingot.json b/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_ingot.json index d45b00b..8663f3d 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_ingot.json +++ b/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_ingot.json @@ -14,18 +14,21 @@ } }, "result": { - "item": "baseelectric:electric_conduit", + "id": "baseelectric:electric_conduit", "count": 6 }, "group": "baseelectric:electric_conduit", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/copper" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/copper" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_rod.json b/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_rod.json index 45953bf..3732f3b 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_rod.json +++ b/src/main/resources/data/baseelectric/recipes/electric_conduit_plastic_rod.json @@ -13,17 +13,20 @@ } }, "result": { - "item": "baseelectric:electric_conduit" + "id": "baseelectric:electric_conduit" }, "group": "baseelectric:electric_conduit", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:rods/copper" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:rods/copper" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_ingot.json b/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_ingot.json index c8d6d8a..22c654f 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_ingot.json +++ b/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_ingot.json @@ -14,18 +14,21 @@ } }, "result": { - "item": "baseelectric:electric_conduit", + "id": "baseelectric:electric_conduit", "count": 6 }, "group": "baseelectric:electric_conduit", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/copper" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:rubber" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/copper" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:rubber" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_rod.json b/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_rod.json index a516ae6..82b10b3 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_rod.json +++ b/src/main/resources/data/baseelectric/recipes/electric_conduit_rubber_rod.json @@ -13,17 +13,20 @@ } }, "result": { - "item": "baseelectric:electric_conduit" + "id": "baseelectric:electric_conduit" }, "group": "baseelectric:electric_conduit", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:rods/copper" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:rubber" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:rods/copper" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:rubber" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_crusher.json b/src/main/resources/data/baseelectric/recipes/electric_crusher.json index 66c42e2..6a9e78d 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_crusher.json +++ b/src/main/resources/data/baseelectric/recipes/electric_crusher.json @@ -22,29 +22,32 @@ } }, "result": { - "item": "baseelectric:electric_crusher" + "id": "baseelectric:electric_crusher" }, "group": "baseelectric:electric_crusher", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:gems/diamond" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:sprockets" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:gems/diamond" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:sprockets" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_drill.json b/src/main/resources/data/baseelectric/recipes/electric_drill.json index 1a74a51..7a19730 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_drill.json +++ b/src/main/resources/data/baseelectric/recipes/electric_drill.json @@ -19,25 +19,28 @@ } }, "result": { - "item": "baseelectric:electric_drill" + "id": "baseelectric:electric_drill" }, "group": "baseelectric:electric_drill", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:storage_blocks/diamond" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:storage_blocks/diamond" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_fabricator.json b/src/main/resources/data/baseelectric/recipes/electric_fabricator.json index 081ff9d..93832ca 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_fabricator.json +++ b/src/main/resources/data/baseelectric/recipes/electric_fabricator.json @@ -19,21 +19,24 @@ } }, "result": { - "item": "baseelectric:electric_fabricator" + "id": "baseelectric:electric_fabricator" }, "group": "baseelectric:electric_fabricator", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_furnace.json b/src/main/resources/data/baseelectric/recipes/electric_furnace.json index 2ddcecd..b136920 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_furnace.json +++ b/src/main/resources/data/baseelectric/recipes/electric_furnace.json @@ -14,13 +14,11 @@ } }, "result": { - "item": "baseelectric:electric_furnace" + "id": "baseelectric:electric_furnace" }, "group": "baseelectric:electric_furnace", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_oven.json b/src/main/resources/data/baseelectric/recipes/electric_oven.json index 6d06a39..135e1ba 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_oven.json +++ b/src/main/resources/data/baseelectric/recipes/electric_oven.json @@ -22,25 +22,28 @@ } }, "result": { - "item": "baseelectric:electric_oven" + "id": "baseelectric:electric_oven" }, "group": "baseelectric:electric_oven", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:glass_panes" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:glass_panes" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_pump.json b/src/main/resources/data/baseelectric/recipes/electric_pump.json index a135d42..78c9261 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_pump.json +++ b/src/main/resources/data/baseelectric/recipes/electric_pump.json @@ -22,21 +22,24 @@ } }, "result": { - "item": "baseelectric:electric_pump" + "id": "baseelectric:electric_pump" }, "group": "baseelectric:electric_pump", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_still.json b/src/main/resources/data/baseelectric/recipes/electric_still.json index 85b8c32..31a065d 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_still.json +++ b/src/main/resources/data/baseelectric/recipes/electric_still.json @@ -22,21 +22,24 @@ } }, "result": { - "item": "baseelectric:electric_still" + "id": "baseelectric:electric_still" }, "group": "baseelectric:electric_still", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_switch.json b/src/main/resources/data/baseelectric/recipes/electric_switch.json index 85a97fe..94dfe6e 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_switch.json +++ b/src/main/resources/data/baseelectric/recipes/electric_switch.json @@ -16,17 +16,20 @@ } }, "result": { - "item": "baseelectric:electric_switch" + "id": "baseelectric:electric_switch" }, "group": "baseelectric:electric_switch", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/electric_track.json b/src/main/resources/data/baseelectric/recipes/electric_track.json index 1a42bfb..31fa7b2 100644 --- a/src/main/resources/data/baseelectric/recipes/electric_track.json +++ b/src/main/resources/data/baseelectric/recipes/electric_track.json @@ -9,7 +9,7 @@ } ], "result": { - "item": "baseelectric:electric_track" + "id": "baseelectric:electric_track" }, "group": "baseelectric:electric_track" } diff --git a/src/main/resources/data/baseelectric/recipes/growth_chamber.json b/src/main/resources/data/baseelectric/recipes/growth_chamber.json index 1fdac8c..a085715 100644 --- a/src/main/resources/data/baseelectric/recipes/growth_chamber.json +++ b/src/main/resources/data/baseelectric/recipes/growth_chamber.json @@ -22,25 +22,28 @@ } }, "result": { - "item": "baseelectric:growth_chamber" + "id": "baseelectric:growth_chamber" }, "group": "baseelectric:growth_chamber", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:microchips" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:microchips" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/growth_chamber_controller.json b/src/main/resources/data/baseelectric/recipes/growth_chamber_controller.json index ea97d35..6278ea9 100644 --- a/src/main/resources/data/baseelectric/recipes/growth_chamber_controller.json +++ b/src/main/resources/data/baseelectric/recipes/growth_chamber_controller.json @@ -22,25 +22,28 @@ } }, "result": { - "item": "baseelectric:growth_chamber_controller" + "id": "baseelectric:growth_chamber_controller" }, "group": "baseelectric:growth_chamber_controller", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:circuit_boards" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:circuit_boards" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/hydroelectric_generator.json b/src/main/resources/data/baseelectric/recipes/hydroelectric_generator.json index ab2e969..6e32bc1 100644 --- a/src/main/resources/data/baseelectric/recipes/hydroelectric_generator.json +++ b/src/main/resources/data/baseelectric/recipes/hydroelectric_generator.json @@ -22,25 +22,28 @@ } }, "result": { - "item": "baseelectric:hydroelectric_generator" + "id": "baseelectric:hydroelectric_generator" }, "group": "baseelectric:hydroelectric_generator", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:sprockets" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:sprockets" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_normal.json b/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_normal.json index cd1a4d9..22f0074 100644 --- a/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_normal.json +++ b/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_normal.json @@ -13,22 +13,25 @@ } }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 3 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "NORMAL" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/copper" - } - ], - "group": "baseelectric:integrated_circuit" + "group": "baseelectric:integrated_circuit", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "NORMAL" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/copper" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_tech.json b/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_tech.json index 228c158..4839f93 100644 --- a/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_tech.json +++ b/src/main/resources/data/baseelectric/recipes/integrated_circuit_copper_tech.json @@ -20,30 +20,33 @@ } }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 3 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "TECH_PROGRESSION" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/redstone" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/copper" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ], - "group": "baseelectric:integrated_circuit" + "group": "baseelectric:integrated_circuit", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "TECH_PROGRESSION" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/redstone" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/copper" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_normal.json b/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_normal.json index f933686..dae0f3d 100644 --- a/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_normal.json +++ b/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_normal.json @@ -13,22 +13,25 @@ } }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 3 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "NORMAL" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/gold" - } - ], - "group": "baseelectric:integrated_circuit" + "group": "baseelectric:integrated_circuit", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "NORMAL" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/gold" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_tech.json b/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_tech.json index 4918b2d..2856987 100644 --- a/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_tech.json +++ b/src/main/resources/data/baseelectric/recipes/integrated_circuit_gold_tech.json @@ -20,30 +20,33 @@ } }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 3 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "TECH_PROGRESSION" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/redstone" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/gold" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ], - "group": "baseelectric:integrated_circuit" + "group": "baseelectric:integrated_circuit", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "TECH_PROGRESSION" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/redstone" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/gold" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_normal.json b/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_normal.json index b278159..f97f9f4 100644 --- a/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_normal.json +++ b/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_normal.json @@ -13,22 +13,25 @@ } }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 3 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "NORMAL" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/tin" - } - ], - "group": "baseelectric:integrated_circuit" + "group": "baseelectric:integrated_circuit", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "NORMAL" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/tin" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_tech.json b/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_tech.json index 62da83a..1cb2cc1 100644 --- a/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_tech.json +++ b/src/main/resources/data/baseelectric/recipes/integrated_circuit_tin_tech.json @@ -20,30 +20,33 @@ } }, "result": { - "item": "baseelectric:integrated_circuit", + "id": "baseelectric:integrated_circuit", "count": 3 }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "TECH_PROGRESSION" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/redstone" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/tin" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ], - "group": "baseelectric:integrated_circuit" + "group": "baseelectric:integrated_circuit", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "TECH_PROGRESSION" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/redstone" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/tin" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/laser_turret_diamond_emerald.json b/src/main/resources/data/baseelectric/recipes/laser_turret_diamond_emerald.json index c577c55..e54d2d0 100644 --- a/src/main/resources/data/baseelectric/recipes/laser_turret_diamond_emerald.json +++ b/src/main/resources/data/baseelectric/recipes/laser_turret_diamond_emerald.json @@ -22,29 +22,32 @@ } }, "result": { - "item": "baseelectric:laser_turret" + "id": "baseelectric:laser_turret" }, "group": "baseelectric:laser_turret", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:gems/diamond" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:gems/emerald" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:gems/diamond" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:gems/emerald" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/laser_turret_emerald_diamond.json b/src/main/resources/data/baseelectric/recipes/laser_turret_emerald_diamond.json index 2a4da72..70a0c25 100644 --- a/src/main/resources/data/baseelectric/recipes/laser_turret_emerald_diamond.json +++ b/src/main/resources/data/baseelectric/recipes/laser_turret_emerald_diamond.json @@ -22,29 +22,32 @@ } }, "result": { - "item": "baseelectric:laser_turret" + "id": "baseelectric:laser_turret" }, "group": "baseelectric:laser_turret", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:gems/diamond" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:gems/emerald" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:gems/diamond" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:gems/emerald" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/lead_acid_battery_dust_sulfur.json b/src/main/resources/data/baseelectric/recipes/lead_acid_battery_dust_sulfur.json index c1afd53..a3fafc7 100644 --- a/src/main/resources/data/baseelectric/recipes/lead_acid_battery_dust_sulfur.json +++ b/src/main/resources/data/baseelectric/recipes/lead_acid_battery_dust_sulfur.json @@ -20,21 +20,24 @@ } }, "result": { - "item": "baseelectric:lead_acid_battery" + "id": "baseelectric:lead_acid_battery" }, "group": "baseelectric:lead_acid_battery", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/sulfur" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/lead" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/sulfur" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/lead" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/lead_acid_battery_sulfur.json b/src/main/resources/data/baseelectric/recipes/lead_acid_battery_sulfur.json index 2924596..d41f1fc 100644 --- a/src/main/resources/data/baseelectric/recipes/lead_acid_battery_sulfur.json +++ b/src/main/resources/data/baseelectric/recipes/lead_acid_battery_sulfur.json @@ -20,21 +20,24 @@ } }, "result": { - "item": "baseelectric:lead_acid_battery" + "id": "baseelectric:lead_acid_battery" }, "group": "baseelectric:lead_acid_battery", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/lead" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:sulfur" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/lead" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:sulfur" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/led_bar.json b/src/main/resources/data/baseelectric/recipes/led_bar.json index 1f38a0d..6efc898 100644 --- a/src/main/resources/data/baseelectric/recipes/led_bar.json +++ b/src/main/resources/data/baseelectric/recipes/led_bar.json @@ -17,22 +17,25 @@ } }, "result": { - "item": "baseelectric:led_bar", + "id": "baseelectric:led_bar", "count": 3 }, "group": "baseelectric:led_bar", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:glass_panes" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:microchips" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:glass_panes" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:microchips" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/lithium_battery.json b/src/main/resources/data/baseelectric/recipes/lithium_battery.json index 105bb57..d757739 100644 --- a/src/main/resources/data/baseelectric/recipes/lithium_battery.json +++ b/src/main/resources/data/baseelectric/recipes/lithium_battery.json @@ -20,25 +20,28 @@ } }, "result": { - "item": "baseelectric:lithium_battery" + "id": "baseelectric:lithium_battery" }, "group": "baseelectric:lithium_battery", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/carbon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/redstone" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/lithium" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/carbon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/redstone" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/lithium" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_nuggets.json b/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_nuggets.json index 4463c7e..5148f81 100644 --- a/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_nuggets.json +++ b/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_nuggets.json @@ -11,13 +11,11 @@ } }, "result": { - "item": "baseelectric:li_ingot" + "id": "baseelectric:li_ingot" }, - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:nuggets/lithium" - } - ], - "group": "baseelectric:li_ingot" + "group": "baseelectric:li_ingot", + "forge:condition": { + "type": "basepower:tag_not_empty", + "tag": "forge:nuggets/lithium" + } } diff --git a/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_ore.json b/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_ore.json index e90ef36..3788528 100644 --- a/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_ore.json +++ b/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_ore.json @@ -3,9 +3,14 @@ "ingredient": { "item": "baseelectric:li_ore" }, - "result": "baseelectric:li_ingot", + "result": { + "id": "baseelectric:li_ingot" + }, "experience": 0.5, "cookingtime": 200, - "conditions": [], - "group": "baseelectric:li_ingot" + "group": "baseelectric:li_ingot", + "forge:condition": { + "type": "forge:and", + "values": [] + } } diff --git a/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_powder.json b/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_powder.json index c5547c7..4204fd5 100644 --- a/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_powder.json +++ b/src/main/resources/data/baseelectric/recipes/lithium_ingot_from_powder.json @@ -3,9 +3,14 @@ "ingredient": { "item": "baseelectric:li_powder" }, - "result": "baseelectric:li_ingot", + "result": { + "id": "baseelectric:li_ingot" + }, "experience": 0.5, "cookingtime": 200, - "conditions": [], - "group": "baseelectric:li_ingot" + "group": "baseelectric:li_ingot", + "forge:condition": { + "type": "forge:and", + "values": [] + } } diff --git a/src/main/resources/data/baseelectric/recipes/lithium_nuggets.json b/src/main/resources/data/baseelectric/recipes/lithium_nuggets.json index 67522fd..ac2d439 100644 --- a/src/main/resources/data/baseelectric/recipes/lithium_nuggets.json +++ b/src/main/resources/data/baseelectric/recipes/lithium_nuggets.json @@ -6,14 +6,12 @@ } ], "result": { - "item": "baseelectric:li_nugget", + "id": "baseelectric:li_nugget", "count": 9 }, "group": "baseelectric:li_nugget", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/lithium" - } - ] + "forge:condition": { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/lithium" + } } diff --git a/src/main/resources/data/baseelectric/recipes/nickel_hydride_battery.json b/src/main/resources/data/baseelectric/recipes/nickel_hydride_battery.json index 3808db2..682f758 100644 --- a/src/main/resources/data/baseelectric/recipes/nickel_hydride_battery.json +++ b/src/main/resources/data/baseelectric/recipes/nickel_hydride_battery.json @@ -20,21 +20,24 @@ } }, "result": { - "item": "baseelectric:nickel_hydride_battery" + "id": "baseelectric:nickel_hydride_battery" }, "group": "baseelectric:nickel_hydride_battery", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/redstone" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/nickel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plastic" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/redstone" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/nickel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plastic" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/photovoltaic_generator.json b/src/main/resources/data/baseelectric/recipes/photovoltaic_generator.json index 85a5f16..e4c862b 100644 --- a/src/main/resources/data/baseelectric/recipes/photovoltaic_generator.json +++ b/src/main/resources/data/baseelectric/recipes/photovoltaic_generator.json @@ -20,29 +20,32 @@ } }, "result": { - "item": "baseelectric:photovoltaic_generator" + "id": "baseelectric:photovoltaic_generator" }, - "conditions": [ - { - "type": "baseelectric:not_recipe_mode", - "mode": "APOCALYPTIC" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:glass_panes" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/silicon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ], - "group": "baseelectric:photovoltaic_generator" + "group": "baseelectric:photovoltaic_generator", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:not_recipe_mode", + "mode": "APOCALYPTIC" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:glass_panes" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/silicon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/plastic_refinery.json b/src/main/resources/data/baseelectric/recipes/plastic_refinery.json index 31867b7..1363ce2 100644 --- a/src/main/resources/data/baseelectric/recipes/plastic_refinery.json +++ b/src/main/resources/data/baseelectric/recipes/plastic_refinery.json @@ -22,25 +22,28 @@ } }, "result": { - "item": "baseelectric:plastic_refinery" + "id": "baseelectric:plastic_refinery" }, "group": "baseelectric:plastic_refinery", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:sprockets" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:sprockets" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/power_supply_unit_iron_normal.json b/src/main/resources/data/baseelectric/recipes/power_supply_unit_iron_normal.json index 5d0c8bf..87f43c1 100644 --- a/src/main/resources/data/baseelectric/recipes/power_supply_unit_iron_normal.json +++ b/src/main/resources/data/baseelectric/recipes/power_supply_unit_iron_normal.json @@ -16,25 +16,28 @@ } }, "result": { - "item": "baseelectric:psu" + "id": "baseelectric:psu" }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "NORMAL" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:circuit_boards" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/iron" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ], - "group": "baseelectric:psu" + "group": "baseelectric:psu", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "NORMAL" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:circuit_boards" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/iron" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_apocalyptic.json b/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_apocalyptic.json index ce3a783..b89ae13 100644 --- a/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_apocalyptic.json +++ b/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_apocalyptic.json @@ -16,25 +16,28 @@ } }, "result": { - "item": "baseelectric:psu" + "id": "baseelectric:psu" }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "APOCALYPTIC" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:circuit_boards" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ], - "group": "baseelectric:psu" + "group": "baseelectric:psu", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "APOCALYPTIC" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:circuit_boards" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_tech.json b/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_tech.json index a6e6a1c..ce84c80 100644 --- a/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_tech.json +++ b/src/main/resources/data/baseelectric/recipes/power_supply_unit_plate_steel_tech.json @@ -16,25 +16,28 @@ } }, "result": { - "item": "baseelectric:psu" + "id": "baseelectric:psu" }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "TECH_PROGRESSION" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:circuit_boards" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ], - "group": "baseelectric:psu" + "group": "baseelectric:psu", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "TECH_PROGRESSION" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:circuit_boards" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/power_supply_unit_steel_normal.json b/src/main/resources/data/baseelectric/recipes/power_supply_unit_steel_normal.json index b8901a5..453b4c3 100644 --- a/src/main/resources/data/baseelectric/recipes/power_supply_unit_steel_normal.json +++ b/src/main/resources/data/baseelectric/recipes/power_supply_unit_steel_normal.json @@ -16,25 +16,28 @@ } }, "result": { - "item": "baseelectric:psu" + "id": "baseelectric:psu" }, - "conditions": [ - { - "type": "baseelectric:recipe_mode", - "mode": "NORMAL" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:circuit_boards" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:ingots/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:wires" - } - ], - "group": "baseelectric:psu" + "group": "baseelectric:psu", + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "baseelectric:recipe_mode", + "mode": "NORMAL" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:circuit_boards" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:ingots/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:wires" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/silicon_blend.json b/src/main/resources/data/baseelectric/recipes/silicon_blend.json index 820bd69..5e34912 100644 --- a/src/main/resources/data/baseelectric/recipes/silicon_blend.json +++ b/src/main/resources/data/baseelectric/recipes/silicon_blend.json @@ -9,17 +9,20 @@ } ], "result": { - "item": "baseelectric:silicon_mix" + "id": "baseelectric:silicon_mix" }, "group": "baseelectric:silicon_mix", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/carbon" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:sand" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/carbon" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:sand" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/silicon_ingot_from_blend.json b/src/main/resources/data/baseelectric/recipes/silicon_ingot_from_blend.json index d843ab4..59c7c2d 100644 --- a/src/main/resources/data/baseelectric/recipes/silicon_ingot_from_blend.json +++ b/src/main/resources/data/baseelectric/recipes/silicon_ingot_from_blend.json @@ -3,9 +3,14 @@ "ingredient": { "item": "baseelectric:silicon_mix" }, - "result": "baseelectric:silicon_ingot", + "result": { + "id": "baseelectric:silicon_ingot" + }, "experience": 0.5, "cookingtime": 200, - "conditions": [], - "group": "baseelectric:silicon_ingot" + "group": "baseelectric:silicon_ingot", + "forge:condition": { + "type": "forge:and", + "values": [] + } } diff --git a/src/main/resources/data/baseelectric/recipes/solder_blend_tin_lead.json b/src/main/resources/data/baseelectric/recipes/solder_blend_tin_lead.json index 4c808f7..ab6faff 100644 --- a/src/main/resources/data/baseelectric/recipes/solder_blend_tin_lead.json +++ b/src/main/resources/data/baseelectric/recipes/solder_blend_tin_lead.json @@ -12,18 +12,21 @@ } ], "result": { - "item": "baseelectric:solder_mix", + "id": "baseelectric:solder_mix", "count": 3 }, "group": "baseelectric:solder_mix", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/lead" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/tin" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/lead" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/tin" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/solder_blend_tin_silver.json b/src/main/resources/data/baseelectric/recipes/solder_blend_tin_silver.json index c9813a0..4c23693 100644 --- a/src/main/resources/data/baseelectric/recipes/solder_blend_tin_silver.json +++ b/src/main/resources/data/baseelectric/recipes/solder_blend_tin_silver.json @@ -12,18 +12,21 @@ } ], "result": { - "item": "baseelectric:solder_mix", + "id": "baseelectric:solder_mix", "count": 3 }, "group": "baseelectric:solder_mix", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/silver" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:dusts/tin" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/silver" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:dusts/tin" + } + ] + } } diff --git a/src/main/resources/data/baseelectric/recipes/solder_from_blend.json b/src/main/resources/data/baseelectric/recipes/solder_from_blend.json index 640976f..26aaa57 100644 --- a/src/main/resources/data/baseelectric/recipes/solder_from_blend.json +++ b/src/main/resources/data/baseelectric/recipes/solder_from_blend.json @@ -3,9 +3,14 @@ "ingredient": { "item": "baseelectric:solder_mix" }, - "result": "baseelectric:solder", + "result": { + "id": "baseelectric:solder" + }, "experience": 0.5, "cookingtime": 200, - "conditions": [], - "group": "baseelectric:solder" + "group": "baseelectric:solder", + "forge:condition": { + "type": "forge:and", + "values": [] + } } diff --git a/src/main/resources/data/baseelectric/recipes/steam_powered_generator.json b/src/main/resources/data/baseelectric/recipes/steam_powered_generator.json index 95d1e72..1dd6849 100644 --- a/src/main/resources/data/baseelectric/recipes/steam_powered_generator.json +++ b/src/main/resources/data/baseelectric/recipes/steam_powered_generator.json @@ -22,29 +22,32 @@ } }, "result": { - "item": "baseelectric:steam_powered_generator" + "id": "baseelectric:steam_powered_generator" }, "group": "baseelectric:steam_powered_generator", - "conditions": [ - { - "type": "basepower:tag_not_empty", - "tag": "forge:conduits/steam" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:frames/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:governors" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:plates/steel" - }, - { - "type": "basepower:tag_not_empty", - "tag": "forge:power_supply_units" - } - ] + "forge:condition": { + "type": "forge:and", + "values": [ + { + "type": "basepower:tag_not_empty", + "tag": "forge:conduits/steam" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:frames/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:governors" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:plates/steel" + }, + { + "type": "basepower:tag_not_empty", + "tag": "forge:power_supply_units" + } + ] + } } diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index baeea15..68e6f8a 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,6 +1,7 @@ { "pack":{ - "pack_format":15, + "pack_format":32, + "supported_formats":{"min_inclusive":32,"max_inclusive":41}, "description":"baseElectric" } } diff --git a/src/test/java/zone/moddev/mc/baseelectric/blocks/NativeBlockContractTest.java b/src/test/java/zone/moddev/mc/baseelectric/blocks/NativeBlockContractTest.java index 00c1790..b327871 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/blocks/NativeBlockContractTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/blocks/NativeBlockContractTest.java @@ -48,7 +48,7 @@ public class NativeBlockContractTest { assertSame(BlockSimplePowerConduit.WEST, ElectricScaffoldBlock.WEST); assertSame(BlockSimplePowerConduit.UP, ElectricScaffoldBlock.UP); assertSame(BlockSimplePowerConduit.DOWN, ElectricScaffoldBlock.DOWN); - for (PathComputationType type : PathComputationType.values()) assertFalse(block.isPathfindable(state, null, BlockPos.ZERO, type)); + for (PathComputationType type : PathComputationType.values()) assertFalse(block.isPathfindable(state, type)); } @Test public void scaffoldInheritsSharedPlacementAndNetworkCallbacks() throws Exception { diff --git a/src/test/java/zone/moddev/mc/baseelectric/blocks/OreHarvestContractTest.java b/src/test/java/zone/moddev/mc/baseelectric/blocks/OreHarvestContractTest.java index 8625adb..633623d 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/blocks/OreHarvestContractTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/blocks/OreHarvestContractTest.java @@ -19,16 +19,7 @@ import static org.junit.Assert.*; public class OreHarvestContractTest { - @BeforeClass public static void bootstrapNativeRegistries() throws Exception { - NativeTestBootstrap.initialize(); - // A plain JVM does not run Forge's resource reload that orders vanilla tiers. - java.lang.reflect.Method sort = net.minecraftforge.common.TierSortingRegistry.class - .getDeclaredMethod("recalculateItemTiers"); - sort.setAccessible(true); - sort.invoke(null); - assertTrue(net.minecraftforge.common.TierSortingRegistry.getSortedTiers() - .contains(net.minecraft.world.item.Tiers.STONE)); - } + @BeforeClass public static void bootstrapNativeRegistries() { NativeTestBootstrap.initialize(); } @Test public void lithiumRetainsStonePickaxeMinimumThroughNativeHarvestChecks() throws Exception { BlockState lithium = new Ore(1).defaultBlockState(); bindHarvestTags(lithium.getBlock(), "baseelectric:li_ore"); @@ -67,6 +58,11 @@ private static void bindHarvestTags(Block block, String id) throws Exception { if (id.equals(value.getAsString())) tags.add(tag); } } + // Vanilla's wooden and golden incorrect-tool tags both include needs_stone_tool. + if (tags.contains(BlockTags.NEEDS_STONE_TOOL)) { + tags.add(net.minecraft.world.item.Tiers.WOOD.getIncorrectBlocksForDrops()); + tags.add(net.minecraft.world.item.Tiers.GOLD.getIncorrectBlocksForDrops()); + } // Bind only the fresh test block's holder; leave the global registry alone. block.builtInRegistryHolder().bindTags(tags); } diff --git a/src/test/java/zone/moddev/mc/baseelectric/entities/ElectricOperationalHydroturbineAnchorTest.java b/src/test/java/zone/moddev/mc/baseelectric/entities/ElectricOperationalHydroturbineAnchorTest.java index 26e1fe4..f55c2fc 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/entities/ElectricOperationalHydroturbineAnchorTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/entities/ElectricOperationalHydroturbineAnchorTest.java @@ -107,7 +107,7 @@ private NoTickWorld() { private static final class ControlEntity extends Entity { ControlEntity(EntityType type, Level world) { super(type, world); } - @Override protected void defineSynchedData() {} + @Override protected void defineSynchedData(net.minecraft.network.syncher.SynchedEntityData.Builder builder) {} @Override protected void readAdditionalSaveData(CompoundTag tag) {} @Override protected void addAdditionalSaveData(CompoundTag tag) {} @Override public Packet getAddEntityPacket() { return null; } diff --git a/src/test/java/zone/moddev/mc/baseelectric/init/VillagesTest.java b/src/test/java/zone/moddev/mc/baseelectric/init/VillagesTest.java index 5ca5156..9f036ba 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/init/VillagesTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/init/VillagesTest.java @@ -4,6 +4,7 @@ import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import zone.moddev.mc.baseelectric.verification.NativeTestBootstrap; import org.junit.BeforeClass; import org.junit.Test; @@ -34,11 +35,14 @@ private static void assertOffer(int minimum, int maximum, boolean upper, int eme }; MerchantOffer offer = Villages.sell(net.minecraft.world.item.Items.APPLE, minimum, maximum) .getOffer(null, random); - CompoundTag nbt = offer.createTag(); + CompoundTag nbt = (CompoundTag) MerchantOffer.CODEC.encodeStart( + NativeTestBootstrap.registries().createSerializationContext(NbtOps.INSTANCE), offer).getOrThrow(); assertEquals("minecraft:emerald", nbt.getCompound("buy").getString("id")); - assertEquals(emeralds, nbt.getCompound("buy").getByte("Count")); + CompoundTag payment = nbt.getCompound("buy"); + assertEquals(emeralds, payment.contains("count") ? payment.getInt("count") : 1); assertEquals("minecraft:apple", nbt.getCompound("sell").getString("id")); - assertEquals(goods, nbt.getCompound("sell").getByte("Count")); + CompoundTag sale = nbt.getCompound("sell"); + assertEquals(goods, sale.contains("count") ? sale.getInt("count") : 1); assertEquals(7, nbt.getInt("maxUses")); assertEquals(0.0F, nbt.getFloat("priceMultiplier"), 0.0F); } diff --git a/src/test/java/zone/moddev/mc/baseelectric/items/BatteryComponentTest.java b/src/test/java/zone/moddev/mc/baseelectric/items/BatteryComponentTest.java new file mode 100644 index 0000000..d20473f --- /dev/null +++ b/src/test/java/zone/moddev/mc/baseelectric/items/BatteryComponentTest.java @@ -0,0 +1,42 @@ +package zone.moddev.mc.baseelectric.items; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; +import org.junit.BeforeClass; +import org.junit.Test; +import zone.moddev.mc.baseelectric.init.Power; +import zone.moddev.mc.baseelectric.verification.NativeTestBootstrap; +import static org.junit.Assert.*; + +public class BatteryComponentTest { + @BeforeClass public static void bootstrap() { NativeTestBootstrap.initialize(); } + + @Test public void vanillaItemUpgradePreservesDepletedChargeAndUnrelatedData() { + CompoundTag custom = LegacyBatteryDataTest.upgradeBattery() + .getCompound("components").getCompound("minecraft:custom_data"); + + BatteryItem battery = new BatteryItem(100, new Item.Properties()); + ItemStack stack = new ItemStack(battery); + assertEquals(100, battery.getEnergy(stack), 0); + stack.set(DataComponents.CUSTOM_DATA, CustomData.of(custom)); + assertEquals(0, battery.getEnergy(stack), 0); + assertEquals(100, battery.addEnergy(stack, 125, Power.ELECTRIC_POWER), 0); + assertEquals("preserved", stack.get(DataComponents.CUSTOM_DATA).copyTag().getString("probe")); + assertEquals(-100, battery.addEnergy(stack, -125, Power.ELECTRIC_POWER), 0); + assertEquals(0, battery.getEnergy(stack.copy()), 0); + } + + @Test public void chargeMutationDoesNotLeakIntoAnItemCopy() { + BatteryItem battery = new BatteryItem(100, new Item.Properties()); + ItemStack original = new ItemStack(battery); + battery.setEnergy(original, 25); + ItemStack copy = original.copy(); + battery.setEnergy(copy, 50); + assertEquals(25, battery.getEnergy(original), 0); + assertEquals(50, battery.getEnergy(copy), 0); + assertFalse(ItemStack.isSameItemSameComponents(original, copy)); + } +} diff --git a/src/test/java/zone/moddev/mc/baseelectric/items/LegacyBatteryDataTest.java b/src/test/java/zone/moddev/mc/baseelectric/items/LegacyBatteryDataTest.java new file mode 100644 index 0000000..97b28ec --- /dev/null +++ b/src/test/java/zone/moddev/mc/baseelectric/items/LegacyBatteryDataTest.java @@ -0,0 +1,37 @@ +package zone.moddev.mc.baseelectric.items; + +import com.mojang.serialization.Dynamic; +import net.minecraft.SharedConstants; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.util.datafix.DataFixers; +import net.minecraft.util.datafix.fixes.References; +import org.junit.Test; +import zone.moddev.mc.baseelectric.verification.NativeTestBootstrap; +import static org.junit.Assert.*; + +public class LegacyBatteryDataTest { + @Test public void nativeDataFixerKeepsTheModdedItemAndMovesItsLegacyCharge() { + CompoundTag upgraded = upgradeBattery(); + assertEquals("baseelectric:lead_acid_battery", upgraded.getString("id")); + assertFalse(upgraded.contains("tag")); + CompoundTag custom = upgraded.getCompound("components").getCompound("minecraft:custom_data"); + assertTrue("Zero charge must be explicitly preserved", custom.contains("energy")); + assertEquals(0, custom.getFloat("energy"), 0); + assertEquals("preserved", custom.getString("probe")); + } + + static CompoundTag upgradeBattery() { + NativeTestBootstrap.initialize(); + CompoundTag item = new CompoundTag(); + item.putString("id", "baseelectric:lead_acid_battery"); + item.putByte("Count", (byte) 1); + CompoundTag tag = new CompoundTag(); + tag.putFloat("energy", 0); + tag.putString("probe", "preserved"); + item.put("tag", tag); + return (CompoundTag) DataFixers.getDataFixer().update(References.ITEM_STACK, + new Dynamic<>(NbtOps.INSTANCE, item), 3465, + SharedConstants.getCurrentVersion().getDataVersion().getVersion()).getValue(); + } +} diff --git a/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricDrillPersistenceTest.java b/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricDrillPersistenceTest.java index f64b2b2..8d31d33 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricDrillPersistenceTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricDrillPersistenceTest.java @@ -4,6 +4,10 @@ import net.minecraft.nbt.ListTag; import net.minecraft.core.Direction; import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import zone.moddev.mc.baseelectric.verification.NativeTestBootstrap; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -19,15 +23,15 @@ public class ElectricDrillPersistenceTest { @Test public void retainsLegacyProgressUntilWorldIsAttached() { ElectricDrillTileEntity drill = new ElectricDrillTileEntity(net.minecraft.core.BlockPos.ZERO, new zone.moddev.mc.baseelectric.machines.ElectricDrillBlock().defaultBlockState()); - drill.load(target(94)); + drill.loadWithComponents(target(94), NativeTestBootstrap.registries()); drill.prepareDataFieldsForSync(); assertEquals(94, drill.getDataFieldArray()[1]); } @Test public void clearsPreviousProgressOnReadingAnUntargetedTile() { ElectricDrillTileEntity drill = new ElectricDrillTileEntity(net.minecraft.core.BlockPos.ZERO, new zone.moddev.mc.baseelectric.machines.ElectricDrillBlock().defaultBlockState()); - drill.load(target(94)); - drill.load(new CompoundTag()); + drill.loadWithComponents(target(94), NativeTestBootstrap.registries()); + drill.loadWithComponents(new CompoundTag(), NativeTestBootstrap.registries()); drill.prepareDataFieldsForSync(); assertEquals(0, drill.getDataFieldArray()[1]); } @@ -73,7 +77,7 @@ public class ElectricDrillPersistenceTest { @Test public void nativeDataFieldsRetainEnergyAndMiningProgress() { ElectricDrillTileEntity drill = new ElectricDrillTileEntity(net.minecraft.core.BlockPos.ZERO, new zone.moddev.mc.baseelectric.machines.ElectricDrillBlock().defaultBlockState()); - drill.load(target(94)); + drill.loadWithComponents(target(94), NativeTestBootstrap.registries()); drill.setEnergy(416.0F, drill.getEnergyType()); drill.prepareDataFieldsForSync(); assertEquals(416.0F, Float.intBitsToFloat(drill.getDataFieldArray()[0]), 0.0F); @@ -82,12 +86,34 @@ public class ElectricDrillPersistenceTest { assertEquals(24.0F, ElectricDrillTileEntity.ENERGY_COST_PROGRESS_TICK, 0.0F); assertEquals(6, drill.numberOfOutputSlots()); - CompoundTag transfer = drill.saveWithoutMetadata(); + // Mod inventories are not visited by vanilla's block-entity item-stack walker. + CompoundTag oldStack = new CompoundTag(); + oldStack.putByte("Slot", (byte) 0); + oldStack.putString("id", "minecraft:diamond"); + oldStack.putByte("Count", (byte) 3); + CompoundTag display = new CompoundTag(); + display.putString("Name", "{\"text\":\"Track transfer payload\"}"); + CompoundTag oldData = new CompoundTag(); + oldData.put("display", display); + oldStack.put("tag", oldData); + ListTag oldItems = new ListTag(); + oldItems.add(oldStack); + CompoundTag legacy = target(94); + legacy.put("Items", oldItems); + drill.loadWithComponents(legacy, NativeTestBootstrap.registries()); + drill.setEnergy(416.0F, drill.getEnergyType()); + ItemStack payload = drill.getOutputSlot(0); + assertEquals(Items.DIAMOND, payload.getItem()); + assertEquals(3, payload.getCount()); + assertEquals(Component.literal("Track transfer payload"), payload.get(DataComponents.CUSTOM_NAME)); + CompoundTag transfer = drill.saveWithoutMetadata(NativeTestBootstrap.registries()); assertEquals(94, transfer.getShort("progress")); ElectricDrillTileEntity placed = new ElectricDrillTileEntity(new BlockPos(5, 70, 9), drill.getBlockState()); - placed.load(transfer); + placed.loadWithComponents(transfer, NativeTestBootstrap.registries()); assertEquals(416.0F, placed.getEnergy(placed.getEnergyType()), 0.0F); assertEquals(new BlockPos(5, 70, 9), placed.getBlockPos()); + assertEquals(3, placed.getOutputSlot(0).getCount()); + org.junit.Assert.assertTrue(ItemStack.isSameItemSameComponents(payload, placed.getOutputSlot(0))); } private static CompoundTag target(int progress) { diff --git a/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalPumpPickupTest.java b/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalPumpPickupTest.java index 1c77a88..1ad31dc 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalPumpPickupTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalPumpPickupTest.java @@ -204,7 +204,7 @@ private static final class RefusingSource extends Block implements BucketPickup defaultBlockState().initCache(); } @Override public FluidState getFluidState(BlockState state) { return Fluids.WATER.getSource(false); } - @Override public net.minecraft.world.item.ItemStack pickupBlock(LevelAccessor world, BlockPos pos, BlockState state) { + @Override public net.minecraft.world.item.ItemStack pickupBlock(net.minecraft.world.entity.player.Player player, LevelAccessor world, BlockPos pos, BlockState state) { calls++; return returnNull ? null : net.minecraft.world.item.ItemStack.EMPTY; } diff --git a/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalSoundBroadcastTest.java b/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalSoundBroadcastTest.java index b6565fd..8ce947e 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalSoundBroadcastTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/machines/ElectricOperationalSoundBroadcastTest.java @@ -124,14 +124,14 @@ private QueryRejectingWorld() { private static final class StubPlayer extends ServerPlayer { boolean spectator; - private StubPlayer() { super(null, null, null); } + private StubPlayer() { super(null, null, null, null); } @Override public boolean isSpectator() { return spectator; } } private static final class RecordingConnection extends ServerGamePacketListenerImpl { int sent; Packet last; - private RecordingConnection() { super(null, null, null); } + private RecordingConnection() { super(null, null, null, null); } @Override public void send(Packet packet) { sent++; last = packet; } } } diff --git a/src/test/java/zone/moddev/mc/baseelectric/machines/GrowthChamberPersistenceTest.java b/src/test/java/zone/moddev/mc/baseelectric/machines/GrowthChamberPersistenceTest.java index fdbd12d..2230400 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/machines/GrowthChamberPersistenceTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/machines/GrowthChamberPersistenceTest.java @@ -13,8 +13,8 @@ public class GrowthChamberPersistenceTest { source.putIntArray("prog", new int[] {245, 468, 627}); for (int pass = 0; pass < 3; pass++) { GrowthChamberTileEntity chamber = new GrowthChamberTileEntity(net.minecraft.core.BlockPos.ZERO, new zone.moddev.mc.baseelectric.machines.GrowthChamberBlock().defaultBlockState()); - chamber.load(source); - CompoundTag saved = chamber.saveWithoutMetadata(); + chamber.loadWithComponents(source, NativeTestBootstrap.registries()); + CompoundTag saved = chamber.saveWithoutMetadata(NativeTestBootstrap.registries()); assertArrayEquals(new byte[] {2, 4, 6}, saved.getByteArray("growth")); assertArrayEquals(new int[] {245, 468, 627}, saved.getIntArray("prog")); source = saved; diff --git a/src/test/java/zone/moddev/mc/baseelectric/machines/Native118ConstructionTest.java b/src/test/java/zone/moddev/mc/baseelectric/machines/Native118ConstructionTest.java index f3a6d2e..359803c 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/machines/Native118ConstructionTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/machines/Native118ConstructionTest.java @@ -1,7 +1,9 @@ package zone.moddev.mc.baseelectric.machines; import net.minecraft.core.BlockPos; +import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; import zone.moddev.mc.baseelectric.verification.NativeTestBootstrap; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; @@ -25,13 +27,13 @@ public class Native118ConstructionTest { assertSame(state, tile.getBlockState()); CompoundTag saved = new CompoundTag(); saved.putInt("x", 0); saved.putInt("y", 1); saved.putInt("z", 2); - tile.load(saved); + tile.loadWithComponents(saved, NativeTestBootstrap.registries()); assertEquals("NBT coordinates cannot move a native block entity", pos, tile.getBlockPos()); assertSame(state, tile.getBlockState()); } } - @Test public void turretPacketUsesConstructorCoordinatesBeforeWorldAttachment() { + @Test public void turretPacketUsesConstructorCoordinatesBeforeWorldAttachment() throws Exception { BlockPos pos = new BlockPos(1531, 91, -475); LaserTurretBlock block = new LaserTurretBlock(false); BlockEntityType type = BlockEntityType.Builder.of(LaserTurretTileEntity::new, block).build(null); @@ -39,18 +41,36 @@ public class Native118ConstructionTest { try { zone.moddev.mc.baseelectric.init.Entities.LASER_TURRET = type; LaserTurretTileEntity turret = new LaserTurretTileEntity(pos, block.defaultBlockState()); + assertNull("The native packet factory needs a level for registry access", turret.getUpdatePacket()); + assertTrue(turret.getUpdateTag(NativeTestBootstrap.registries()).contains("player")); + turret.setOpticPosition(); + assertEquals(pos, turret.getBlockPos()); + + Class allocator = Class.forName("sun.misc.Unsafe"); + var unsafe = allocator.getDeclaredField("theUnsafe"); + unsafe.setAccessible(true); + PacketWorld level = (PacketWorld) allocator.getMethod("allocateInstance", Class.class) + .invoke(unsafe.get(null), PacketWorld.class); + turret.setLevel(level); var packet = turret.getUpdatePacket(); assertEquals(pos, packet.getPos()); assertSame(type, packet.getType()); assertEquals(java.util.Set.of("energy", "lock"), packet.getTag().getAllKeys()); - assertTrue(turret.getUpdateTag().contains("player")); - turret.setOpticPosition(); - assertEquals(pos, turret.getBlockPos()); } finally { zone.moddev.mc.baseelectric.init.Entities.LASER_TURRET = previous; } } + private static final class PacketWorld extends ServerLevel { + private PacketWorld() { + super(null, null, null, null, null, null, null, false, 0L, java.util.List.of(), false, null); + } + + @Override public RegistryAccess registryAccess() { + return NativeTestBootstrap.registries(); + } + } + @Test public void ledOnlyOffersItsOwnNativeTicker() { LEDBlock block = new LEDBlock(); BlockEntityType type = BlockEntityType.Builder.of(LEDTileEntity::new, block).build(null); diff --git a/src/test/java/zone/moddev/mc/baseelectric/recipe/RecipeConditionsTest.java b/src/test/java/zone/moddev/mc/baseelectric/recipe/RecipeConditionsTest.java index 8c5ccc6..4dd882d 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/recipe/RecipeConditionsTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/recipe/RecipeConditionsTest.java @@ -2,6 +2,7 @@ import java.util.Locale; import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; import org.junit.Test; import net.minecraftforge.common.crafting.conditions.ICondition; import zone.moddev.mc.basepower.PowerAdvantage; @@ -13,19 +14,17 @@ public class RecipeConditionsTest { RecipeMode original = PowerAdvantage.recipeMode; try { for (boolean inverted : new boolean[] {false, true}) { - RecipeConditions.ModeSerializer serializer = new RecipeConditions.ModeSerializer(inverted); + var codec = inverted ? RecipeConditions.NOT_MATCH : RecipeConditions.MATCH; for (RecipeMode expected : RecipeMode.values()) { JsonObject source = new JsonObject(); source.addProperty("mode", expected.name().toLowerCase(Locale.ROOT)); - RecipeConditions.ModeCondition condition = serializer.read(source); - assertEquals(serializer.getID(), condition.getID()); - JsonObject saved = new JsonObject(); - serializer.write(saved, condition); - assertEquals(source, saved); + var condition = codec.codec().parse(JsonOps.INSTANCE, source).getOrThrow(); + assertSame(codec, condition.codec()); + assertEquals(source, codec.codec().encodeStart(JsonOps.INSTANCE, condition).getOrThrow()); for (RecipeMode selected : RecipeMode.values()) { PowerAdvantage.recipeMode = selected; - assertEquals((selected == expected) != inverted, condition.test()); - assertEquals(condition.test(), condition.test(ICondition.IContext.EMPTY)); + assertEquals((selected == expected) != inverted, + condition.test(ICondition.IContext.EMPTY, JsonOps.INSTANCE)); } } } @@ -40,7 +39,8 @@ public class RecipeConditionsTest { Locale.setDefault(new Locale("tr", "TR")); JsonObject json = new JsonObject(); json.addProperty("mode", "apocalyptic"); - new RecipeConditions.ModeSerializer(false).read(json); + assertEquals(RecipeMode.APOCALYPTIC, + RecipeConditions.MATCH.codec().parse(JsonOps.INSTANCE, json).getOrThrow().mode()); } finally { Locale.setDefault(original); } diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/BaseMetalsRawRecipeContractTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/BaseMetalsRawRecipeContractTest.java index 9cf55f2..0b38880 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/BaseMetalsRawRecipeContractTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/BaseMetalsRawRecipeContractTest.java @@ -21,8 +21,8 @@ public class BaseMetalsRawRecipeContractTest { assertEquals("basemetals:crushing", recipe.get("type").getAsString()); assertEquals("forge:" + (input.equals("ore") ? "ores/" : "raw_materials/") + metal, recipe.getAsJsonObject("ingredient").get("tag").getAsString()); - assertEquals("basemetals:" + metal + "_powder", recipe.getAsJsonObject("result").get("item").getAsString()); - // Base Metals delegates to CraftingHelper, whose omitted count defaults to one. + assertEquals("basemetals:" + metal + "_powder", recipe.getAsJsonObject("result").get("id").getAsString()); + // The native item stack codec defaults an omitted count to one. assertEquals(input.equals("ore") ? 2 : 1, GsonHelper.getAsInt(recipe.getAsJsonObject("result"), "count", 1)); } } diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/BlockLootResourceTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/BlockLootResourceTest.java index a0737bb..fdce5c0 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/BlockLootResourceTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/BlockLootResourceTest.java @@ -35,7 +35,10 @@ public class BlockLootResourceTest { @Test public void resourcePackDeclaresTheNativeOneTwentyOneFormat() throws Exception { JsonObject pack = read(Paths.get("src/main/resources/pack.mcmeta")).getAsJsonObject("pack"); - assertEquals(15, pack.get("pack_format").getAsInt()); + assertEquals(32, pack.get("pack_format").getAsInt()); + JsonObject formats = pack.getAsJsonObject("supported_formats"); + assertEquals(32, formats.get("min_inclusive").getAsInt()); + assertEquals(41, formats.get("max_inclusive").getAsInt()); assertFalse(pack.has("forge:server_data_pack_format")); } diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/BuildWorkflowContractTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/BuildWorkflowContractTest.java index 3c3a8a4..c5b17aa 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/BuildWorkflowContractTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/BuildWorkflowContractTest.java @@ -11,7 +11,7 @@ public class BuildWorkflowContractTest { 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"}) { + for (String version : new String[] {"25.0.3+9.0.LTS", "8.0.502+7", "21.0.7+6.0.LTS"}) { int pin = source.indexOf("java-version: '" + version + "'"); assertTrue(workflow + " missing pinned JDK " + version, pin >= 0 && pin < setup); } @@ -35,42 +35,26 @@ public class BuildWorkflowContractTest { String source = new String(Files.readAllBytes(Paths.get(".github/workflows", workflow)), StandardCharsets.UTF_8); int policy = source.indexOf("git config --global core.autocrlf false"); int published = source.indexOf("bash .github/verify-published-pins.sh"); - int pins = source.indexOf("bash .github/scripts/forge47-dependencies.sh pins"); - int dependencyBuild = source.indexOf("bash .github/scripts/forge47-dependencies.sh build"); assertTrue(policy > 0); - assertTrue(policy < published && published < pins); - for (String repository : new String[] {"OreSpawn", "BaseMetals", "basePower"}) { - assertTrue(pins < source.indexOf("repository: MinecraftModDevelopmentMods/" + repository)); + assertTrue(policy < published); + for (String repository : new String[] {"OreSpawn", "basePower"}) { + assertTrue(published < source.indexOf("repository: MinecraftModDevelopmentMods/" + repository)); } - assertTrue(source.contains("ref: ${{ steps.pins.outputs.orespawn_ref }}")); - assertTrue(source.contains("ref: ${{ steps.pins.outputs.basemetals_ref }}")); - assertTrue(source.contains("ref: ${{ steps.pins.outputs.power_ref }}")); - assertTrue(dependencyBuild > source.indexOf("ref: ${{ steps.pins.outputs.power_ref }}")); - assertTrue(source.indexOf("\"-Pforge47MavenizerJar=$MAVENIZER\"") > dependencyBuild); - assertTrue(source.contains("MAVENIZER: ${{ steps.dependencies.outputs.mavenizer }}")); - assertTrue(source.contains("branches: [master-1.20.1")); - assertFalse(source.contains("1.17.1")); + assertTrue(source.contains("ref: ${{ steps.public-pins.outputs.orespawn_ref }}")); + assertTrue(source.contains("ref: ${{ steps.public-pins.outputs.power_ref }}")); + assertTrue(source.contains("branches: [master-1.20.6")); + assertTrue(source.contains("-Pforge50MavenizerJar=$MAVENIZER")); + assertTrue(source.contains("-PpowerAdvantageDeobfJar=$POWER_PLAYER")); + assertFalse(source.contains("forge47")); if (workflow.equals("ci.yml")) { - assertTrue(source.contains("POWER_PLAYER: ${{ steps.public-pins.outputs.power_player }}")); + assertTrue(source.contains("-PforgeInstallerJar=$FORGE_INSTALLER")); } } - String script = Files.readString(Paths.get(".github/scripts/forge47-dependencies.sh")); - assertTrue(script.contains("$(value poweradvantage_pin_state)") && script.contains("'MERGED_SOURCE'")); + String script = Files.readString(Paths.get(".github/verify-published-pins.sh")); assertTrue(script.contains("=~ ^[a-f0-9]{40}$") && script.contains("=~ ^[A-F0-9]{64}$")); - for (String dependency : new String[] {"orespawn", "basemetals", "power"}) { - assertTrue(script.contains("git -C \"$" + dependency + "\" rev-parse HEAD")); + for (String dependency : new String[] {"poweradvantage", "basemetals", "orespawn"}) { + assertTrue(script.contains("$(value " + dependency + "_public_file_id)")); } - assertTrue(script.contains("$orespawn/ci-fixtures/tools/minecraft-mavenizer-0.5.21-orespawn-compat.jar")); - assertTrue(script.contains("check_hash \"$mavenizer\" '416DCA4797BC55826F0DDCF03FDC405F1990FC15C2133FA27A1F143BF7976177'")); - int metalsBuild = script.indexOf("(cd \"$basemetals\" && ./gradlew"); - int powerBuild = script.indexOf("(cd \"$power\" && ./gradlew"); - assertTrue(metalsBuild > 0 && powerBuild > metalsBuild); - String metals = script.substring(metalsBuild, powerBuild); - assertFalse(metals.contains("-I ") || metals.contains("-Pforge47Mavenizer")); - String power = script.substring(powerBuild); - assertFalse(power.contains("-I ") || power.contains("MavenizerScript")); - assertTrue(power.contains("\"-Pforge47MavenizerJar=$mavenizer\"")); - assertTrue(script.contains("git -C \"$basemetals\" diff --exit-code HEAD --")); - assertTrue(script.contains("git -C \"$power\" diff --exit-code HEAD --")); + assertTrue(script.contains("sha256sum -c -")); } } diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeRegistrationThreadTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeRegistrationThreadTest.java index 58ecefb..936b95f 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeRegistrationThreadTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeRegistrationThreadTest.java @@ -1,49 +1,19 @@ package zone.moddev.mc.baseelectric.resources; -import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; 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/baseelectric/ElectricAdvantage.class")) { - assertNotNull(input); - new ClassReader(input).accept(node, 0); - } - String conditions = "zone/moddev/mc/baseelectric/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/event/lifecycle/FMLCommonSetupEvent") - && call.name.equals("enqueueWork") && 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); + Path root = Path.of("src/main/java/zone/moddev/mc/baseelectric"); + String entry = Files.readString(root.resolve("ElectricAdvantage.java")); + String conditions = Files.readString(root.resolve("recipe/RecipeConditions.java")); + assertTrue(entry.contains("RecipeConditions.register(context.getModEventBus())")); + assertFalse(entry.contains("RecipeConditions::register")); + assertTrue(conditions.contains("DeferredRegister.create(ForgeRegistries.Keys.CONDITION_SERIALIZERS")); + assertTrue(conditions.contains("SERIALIZERS.register(bus)")); + assertFalse(conditions.contains("CraftingHelper")); } } diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeResourceTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeResourceTest.java index 5c2aed4..064f505 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeResourceTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeResourceTest.java @@ -31,6 +31,8 @@ public class RecipeResourceTest { String text = new String(Files.readAllBytes(file), StandardCharsets.UTF_8); JsonObject json = new JsonParser().parse(text).getAsJsonObject(); String type = json.get("type").getAsString(); + assertTrue(file + " must use the 1.20.6 result stack codec", json.getAsJsonObject("result").has("id")); + assertFalse(file + " still has pre-1.20.6 Forge conditions", json.has("conditions")); assertTrue(file + " has unsupported serializer " + type, "minecraft:crafting_shaped".equals(type) || "minecraft:crafting_shapeless".equals(type) diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeUnlockContractTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeUnlockContractTest.java index 31ce615..26dbaba 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeUnlockContractTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/RecipeUnlockContractTest.java @@ -18,8 +18,8 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.mojang.serialization.JsonOps; import net.minecraft.advancements.critereon.ItemPredicate; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.junit.Test; import static org.junit.Assert.*; @@ -80,18 +80,18 @@ public class RecipeUnlockContractTest { @Test public void nativeParserRestrictsItemArraysButSilentlyIgnoresTheLegacySingularKey() { NativeTestBootstrap.initialize(); JsonObject nativeShape = new JsonParser().parse("{\"items\":[\"minecraft:apple\"]}").getAsJsonObject(); - ItemPredicate nativePredicate = ItemPredicate.fromJson(nativeShape); - assertTrue(nativePredicate.matches(new ItemStack(Items.APPLE))); + ItemPredicate nativePredicate = ItemPredicate.CODEC.parse(NativeTestBootstrap.registries().createSerializationContext(JsonOps.INSTANCE), nativeShape).getOrThrow(); + assertTrue(nativePredicate.items().orElseThrow().contains(Items.APPLE.builtInRegistryHolder())); assertFalse("An unrelated item must not unlock an apple recipe", - nativePredicate.matches(new ItemStack(Items.DIRT))); + nativePredicate.items().orElseThrow().contains(Items.DIRT.builtInRegistryHolder())); assertEquals("item:minecraft:apple", unlockPredicateKey(nativeShape)); JsonObject legacyShape = new JsonParser().parse("{\"item\":\"minecraft:apple\"}").getAsJsonObject(); assertEquals("The old singular spelling remains valid for recipe ingredients", "item:minecraft:apple", ingredientKey(legacyShape)); - ItemPredicate legacyPredicate = ItemPredicate.fromJson(legacyShape); + ItemPredicate legacyPredicate = ItemPredicate.CODEC.parse(NativeTestBootstrap.registries().createSerializationContext(JsonOps.INSTANCE), legacyShape).getOrThrow(); assertTrue("Negative control: the native parser silently loses this item's restriction", - legacyPredicate.matches(new ItemStack(Items.DIRT))); + legacyPredicate.items().isEmpty()); assertThrows("The resource contract must reject that silently unrestricted trigger", AssertionError.class, () -> unlockPredicateKey(legacyShape)); for (String malformed : new String[] { @@ -113,8 +113,11 @@ public class RecipeUnlockContractTest { JsonObject criterion = unlock.getAsJsonObject("criteria").getAsJsonObject("has_recipe"); assertEquals("minecraft:recipe_unlocked", criterion.get("trigger").getAsString()); assertEquals(id, criterion.getAsJsonObject("conditions").get("recipe").getAsString()); - assertFalse("Forge recipe conditions are not valid advancement conditions", unlock.has("conditions")); + assertFalse("Recipe availability must not remove the unlock: " + id, unlock.has("forge:condition")); + assertFalse(unlock.has("conditions")); } + assertTrue("The material-gated control must remain conditional", + read(DATA.resolve("recipes/alkaline_battery.json")).has("forge:condition")); } @Test public void recipeBookGroupsIdentifyTheOutputNotABroadMachineCategory() throws IOException { @@ -123,7 +126,7 @@ public class RecipeUnlockContractTest { if (!crafting(recipe)) continue; JsonElement result = recipe.get("result"); String output = result.isJsonPrimitive() ? result.getAsString() - : result.getAsJsonObject().get("item").getAsString(); + : result.getAsJsonObject().get("id").getAsString(); assertTrue("Missing output-specific group: " + file, recipe.has("group")); assertEquals("Different items must not share a recipe-book cell: " + file, output, recipe.get("group").getAsString()); @@ -144,10 +147,11 @@ private static String ingredientKey(JsonObject predicate) { private static String unlockPredicateKey(JsonObject predicate) { assertEquals("Unlock predicates must constrain exactly one item or tag", 1, predicate.size()); assertFalse("The native parser ignores the singular item key in advancement predicates", predicate.has("item")); - if (predicate.has("tag")) { - assertTrue("A tag predicate must be a string", predicate.get("tag").isJsonPrimitive() - && predicate.getAsJsonPrimitive("tag").isString()); - return "tag:" + predicate.get("tag").getAsString(); + if (predicate.has("items") && predicate.get("items").isJsonPrimitive()) { + assertTrue(predicate.getAsJsonPrimitive("items").isString()); + String tag = predicate.get("items").getAsString(); + assertTrue("A tag predicate must use a hash prefix", tag.startsWith("#") && tag.length() > 1); + return "tag:" + tag.substring(1); } assertTrue("A native item predicate requires the items array", predicate.has("items") && predicate.get("items").isJsonArray()); diff --git a/src/test/java/zone/moddev/mc/baseelectric/resources/ShaderResourceContractTest.java b/src/test/java/zone/moddev/mc/baseelectric/resources/ShaderResourceContractTest.java index 7f1b305..b07c917 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/resources/ShaderResourceContractTest.java +++ b/src/test/java/zone/moddev/mc/baseelectric/resources/ShaderResourceContractTest.java @@ -23,7 +23,8 @@ public class ShaderResourceContractTest { assertNotNull(getClass().getResource("/assets/minecraft/shaders/core/rendertype_entity_translucent.fsh")); var uniformNames = java.util.stream.StreamSupport.stream(json.getAsJsonArray("uniforms").spliterator(), false) .map(value -> value.getAsJsonObject().get("name").getAsString()).collect(Collectors.toSet()); - assertTrue(uniformNames.containsAll(java.util.Set.of("IViewRotMat", "FogShape"))); + assertTrue(uniformNames.contains("FogShape")); + assertFalse(uniformNames.contains("IViewRotMat")); } @Test public void noDiffuseLightingDoesNotRemoveLightmapOrOverlaySampling() throws Exception { @@ -33,7 +34,7 @@ public class ShaderResourceContractTest { assertTrue(vertex.contains("overlayColor = texelFetch(Sampler1, UV1, 0);")); assertFalse(vertex.contains("minecraft_mix_light")); assertTrue(vertex.contains("#moj_import ")); - String fog = "vertexDistance = fog_distance(ModelViewMat, IViewRotMat * Position, FogShape);"; + String fog = "vertexDistance = fog_distance(Position, FogShape);"; assertTrue(vertex.contains(fog)); try (var vanilla = getClass().getResourceAsStream("/assets/minecraft/shaders/core/rendertype_entity_translucent.vsh")) { assertNotNull(vanilla); diff --git a/src/test/java/zone/moddev/mc/baseelectric/verification/NativeTestBootstrap.java b/src/test/java/zone/moddev/mc/baseelectric/verification/NativeTestBootstrap.java index 600b1da..db9f862 100644 --- a/src/test/java/zone/moddev/mc/baseelectric/verification/NativeTestBootstrap.java +++ b/src/test/java/zone/moddev/mc/baseelectric/verification/NativeTestBootstrap.java @@ -3,11 +3,20 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; +import cpw.mods.modlauncher.api.IModuleLayerManager; import net.minecraft.SharedConstants; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.server.Bootstrap; import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.ModLoader; +import net.minecraftforge.fml.loading.FMLLoader; +import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistry; @@ -25,34 +34,71 @@ public static synchronized void initialize() { if (ready) return; SharedConstants.tryDetectVersion(); Bootstrap.bootStrap(); + initializeEmptyModList(); // The plain test JVM has no FML registration phase after vanilla bootstrap. GameData.unfreezeData(); ready = true; } + private static void initializeEmptyModList() { + if (FMLLoader.getLoadingModList() != null) return; + try { + // Item components post native FML events even in a worldless JVM. + Field discovered = FMLLoader.class.getDeclaredField("loadingModList"); + discovered.setAccessible(true); + LoadingModList loading = LoadingModList.of(List.of(), List.of(), null); + loading.setBrokenFiles(List.of()); + discovered.set(null, loading); + Field layers = FMLLoader.class.getDeclaredField("moduleLayerManager"); + layers.setAccessible(true); + layers.set(null, (IModuleLayerManager) ignored -> Optional.of(ModuleLayer.boot())); + ModList mods = ModList.of(List.of(), List.of()); + Method load = ModList.class.getDeclaredMethod("setLoadedMods", List.class); + load.setAccessible(true); + load.invoke(mods, List.of()); + Field valid = ModLoader.class.getDeclaredField("loadingStateValid"); + valid.setAccessible(true); + valid.setBoolean(ModLoader.get(), true); + } catch (ReflectiveOperationException failure) { + throw new IllegalStateException("Cannot prepare the Forge 50 worldless test context", failure); + } + } + + public static RegistryAccess.Frozen registries() { + return RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY); + } + public static synchronized void registerVanillaFluidTypes() throws ReflectiveOperationException { initialize(); if (ForgeRegistries.FLUID_TYPES.get() != null) return; // Run the same narrow Forge registry phases as Power's worldless entity fixtures. NewRegistryEvent event = new NewRegistryEvent(); - Field types = ForgeRegistries.class.getDeclaredField("DEFERRED_FLUID_TYPES"); - types.setAccessible(true); - Method create = DeferredRegister.class.getDeclaredMethod("createRegistry", NewRegistryEvent.class); + Field registries = ForgeRegistries.class.getDeclaredField("registries"); + registries.setAccessible(true); + var deferred = ((List) registries.get(null)).stream() + .map(candidate -> (DeferredRegister) candidate) + .filter(candidate -> candidate.getRegistryKey().equals(ForgeRegistries.Keys.FLUID_TYPES)) + .findFirst().orElseThrow(); + // Dispatch the two native events directly; plain JUnit has no EventBus bytecode transform. + Class dispatcher = Class.forName(DeferredRegister.class.getName() + "$EventDispatcher"); + Constructor listener = dispatcher.getDeclaredConstructor(DeferredRegister.class); + listener.setAccessible(true); + Method create = dispatcher.getDeclaredMethod("createRegistry", NewRegistryEvent.class); create.setAccessible(true); - create.invoke(types.get(null), event); + create.invoke(listener.newInstance(deferred), event); Method fill = NewRegistryEvent.class.getDeclaredMethod("fill"); fill.setAccessible(true); fill.invoke(event); - Field vanilla = ForgeMod.class.getDeclaredField("VANILLA_FLUID_TYPES"); - vanilla.setAccessible(true); - Method register = DeferredRegister.class.getDeclaredMethod("addEntries", RegisterEvent.class); - register.setAccessible(true); Constructor registerEvent = RegisterEvent.class.getDeclaredConstructor( ResourceKey.class, ForgeRegistry.class, Registry.class); registerEvent.setAccessible(true); - register.invoke(vanilla.get(null), registerEvent.newInstance( + Field vanilla = ForgeMod.class.getDeclaredField("VANILLA_FLUID_TYPES"); + vanilla.setAccessible(true); + Method handle = dispatcher.getDeclaredMethod("handleEvent", RegisterEvent.class); + handle.setAccessible(true); + handle.invoke(listener.newInstance(vanilla.get(null)), registerEvent.newInstance( ForgeRegistries.Keys.FLUID_TYPES, ForgeRegistries.FLUID_TYPES.get(), null)); } } diff --git a/tools/generate-recipe-unlocks.js b/tools/generate-recipe-unlocks.js index 4c3e37c..19ee50b 100644 --- a/tools/generate-recipe-unlocks.js +++ b/tools/generate-recipe-unlocks.js @@ -31,7 +31,7 @@ for (const file of fs.readdirSync(recipes).filter(name => name.endsWith('.json') unique.forEach((ingredient, index) => { criteria[`has_ingredient_${index + 1}`] = { trigger: 'minecraft:inventory_changed', - conditions: {items: [ingredient.item ? {items: [ingredient.item]} : ingredient]} + conditions: {items: [{items: ingredient.item ? [ingredient.item] : '#' + ingredient.tag}]} }; }); criteria.has_recipe = {trigger: 'minecraft:recipe_unlocked', conditions: {recipe: id}}; @@ -39,6 +39,7 @@ for (const file of fs.readdirSync(recipes).filter(name => name.endsWith('.json') parent: 'minecraft:recipes/root', criteria, requirements: [Object.keys(criteria)], rewards: {recipes: [id]} }; + // Discovery survives recipe-mode and optional-provider changes. const text = JSON.stringify(advancement, null, 2) + '\n'; const target = path.join(output, file); expected.add(file); diff --git a/tools/verification/Invoke-ElectricPackagedSmoke.ps1 b/tools/verification/Invoke-ElectricPackagedSmoke.ps1 index 01323de..46a09cf 100644 --- a/tools/verification/Invoke-ElectricPackagedSmoke.ps1 +++ b/tools/verification/Invoke-ElectricPackagedSmoke.ps1 @@ -30,7 +30,7 @@ $target = "$($pins.minecraft_version)-$($pins.forge_version)" $forgeDir = "libraries/net/minecraftforge/forge/$target" $winArgs = "$forgeDir/win_args.txt" $receipt = [ordered]@{ - status = 'FAIL'; scope = 'Packaged, loopback-only Forge 1.20.1 dedicated server smoke; no client or migration proof' + status = 'FAIL'; scope = 'Packaged Forge 1.20.6 dedicated server and legacy inventory probe; no client or whole-world upgrade proof' baseMetalsIncluded = !$WithoutBaseMetals seed = $seed; java = $javaPath; inputs = @(); checks = [ordered]@{}; exitCode = $null; error = $null } @@ -63,24 +63,23 @@ function Send-Command([string]$Command) { } try { - if ($target -cne '1.20.1-47.4.10' -or $pins.mod_version -cne '2.2.13.120011') { - throw 'This smoke runner is bound to baseElectric 2.2.13.120011 on Forge 47.4.10.' + if ($target -cne '1.20.6-50.2.0' -or $pins.mod_version -cne '2.2.14.120061') { + throw 'This smoke runner is bound to baseElectric 2.2.14.120061 on Forge 50.2.0.' } if ($pins.poweradvantage_pin_state -ne 'MERGED_SOURCE' -or $PowerSha256 -ne $pins.poweradvantage_runtime_sha256) { throw 'Packaged smoke requires the exact source-pinned basePower player JAR.' } $receipt.powerSourceRef = $pins.poweradvantage_source_ref $javaRelease = Join-Path (Split-Path (Split-Path $javaPath)) 'release' - if ((Get-Content -LiteralPath $javaRelease -Raw) -notmatch 'JAVA_VERSION="17\.') { - throw 'The dedicated-server smoke requires Java 17.' + if ((Get-Content -LiteralPath $javaRelease -Raw) -notmatch 'JAVA_VERSION="21\.') { + throw 'The dedicated-server smoke requires Java 21.' } $receipt.javaRelease = (Get-FileHash -LiteralPath $javaRelease).Hash $receipt.javaSha256 = (Get-FileHash -LiteralPath $javaPath).Hash $argsText = Get-Content -LiteralPath (Join-Path $seed $winArgs) -Raw - foreach ($marker in @('--launchTarget forgeserver', "--fml.forgeVersion $($pins.forge_version)", - "--fml.mcVersion $($pins.minecraft_version)", "--fml.mcpVersion $($pins.mcp_version)")) { - if (!$argsText.Contains($marker)) { throw "Unexpected Forge seed arguments: missing $marker" } - } + $shim = "forge-$target-shim.jar" + if (!$argsText.Contains("-jar $shim")) { throw 'Unexpected Forge 50 server argument file.' } + $receipt.shimSha256 = (Get-FileHash -LiteralPath (Join-Path $seed $shim)).Hash $receipt.seedArgumentsSha256 = (Get-FileHash -LiteralPath (Join-Path $seed $winArgs)).Hash $forgeUniversal = Join-Path $seed "$forgeDir/forge-$target-universal.jar" $receipt.forgeUniversalSha256 = (Get-FileHash -LiteralPath $forgeUniversal).Hash @@ -88,7 +87,10 @@ try { throw 'Pass the existing accepted EULA from the local smoke fixture.' } Copy-Item -LiteralPath (Join-Path $seed 'libraries') -Destination $output -Recurse + Copy-Item -LiteralPath (Join-Path $seed $shim) -Destination $output Copy-Item -LiteralPath $EulaFile -Destination (Join-Path $output 'eula.txt') + $config = (New-Item -ItemType Directory -Path (Join-Path $output 'config')).FullName + [IO.File]::WriteAllText((Join-Path $config 'fml.toml'), "versionCheck = false`n") $modDir = (New-Item -ItemType Directory -Path (Join-Path $output 'mods')).FullName $modInputs = @( @{ path = $ElectricJar; hash = $ElectricSha256; name = "baseElectric-$($pins.mod_version).jar" }, @@ -109,8 +111,8 @@ try { $receipt.inputs += [ordered]@{ path = $actual.Path; sha256 = $actual.Hash; copy = $copy } } [IO.File]::WriteAllLines((Join-Path $output 'server.properties'), @( - 'server-ip=127.0.0.1', 'server-port=0', 'enable-rcon=false', 'enable-query=false', - 'level-name=electric-smoke', 'level-seed=120011', 'generate-structures=false', + 'server-ip=127.0.0.1', 'server-port=0', 'online-mode=false', 'enable-rcon=false', 'enable-query=false', + 'level-name=electric-smoke', 'level-seed=120061', 'generate-structures=false', 'view-distance=3', 'simulation-distance=3', 'spawn-protection=0' )) $start = [Diagnostics.ProcessStartInfo]::new($javaPath) @@ -148,12 +150,30 @@ try { throw "Drill did not serialize the expected $key tag." } } + Send-Command 'item replace block 0 300 0 container.0 with baseelectric:lead_acid_battery[minecraft:custom_data={energy:0.0f,probe:"electric-smoke"}]' + $receipt.checks.drillBatterySlot = Wait-ForLine 'Replaced a slot at 0, 300, 0' 20 + Send-Command 'data get block 0 300 0 Items' + $receipt.checks.drillBatteryData = Wait-ForLine 'block data:.*baseelectric:lead_acid_battery' 20 + if ($receipt.checks.drillBatteryData -notmatch 'minecraft:custom_data' -or + $receipt.checks.drillBatteryData -notmatch 'energy:\s*0(?:\.0)?f' -or + $receipt.checks.drillBatteryData -notmatch 'electric-smoke') { + throw 'The live drill inventory did not retain the battery components.' + } + Send-Command 'data merge block 0 300 0 {Items:[{Slot:0b,id:"baseelectric:lead_acid_battery",Count:1b,tag:{energy:0.0f,probe:"legacy-inventory"}}]}' + $receipt.checks.legacyBatteryMerge = Wait-ForLine 'Modified block data of 0, 300, 0' 20 + Send-Command 'data get block 0 300 0 Items' + $receipt.checks.legacyBatteryData = Wait-ForLine 'block data:.*baseelectric:lead_acid_battery' 20 + if ($receipt.checks.legacyBatteryData -notmatch 'minecraft:custom_data' -or + $receipt.checks.legacyBatteryData -notmatch 'energy:\s*0(?:\.0)?f' -or + $receipt.checks.legacyBatteryData -notmatch 'legacy-inventory') { + throw 'The live drill did not upgrade its 1.20.1 battery inventory entry.' + } Send-Command 'setblock 1 300 0 baseelectric:sulfur_ore' $receipt.checks.placeSulfur = Wait-ForLine 'Changed the block at 1, 300, 0' 20 Send-Command 'setblock 2 299 0 minecraft:stone' $receipt.checks.sulfurLanding = Wait-ForLine 'Changed the block at 2, 299, 0' 20 Send-Command 'loot spawn 2 301 0 mine 1 300 0 minecraft:wooden_pickaxe' - $receipt.checks.sulfurLoot = Wait-ForLine 'Dropped [1-4] \[Powdered Sulfur\] from loot table baseelectric:blocks/sulfur_ore' 20 + $receipt.checks.sulfurLoot = Wait-ForLine 'Dropped [1-4] \[(?:Powdered Sulfur|item\.baseelectric\.sulfur_powder)\] from loot table baseelectric:blocks/sulfur_ore' 20 for ($attempt = 0; $attempt -lt 5; $attempt++) { Send-Command 'data get entity @e[type=minecraft:item,sort=nearest,limit=1,x=2,y=301,z=0,distance=..5] Item' $result = Wait-ForLine 'entity data:|No entity was found' 10 @@ -162,7 +182,7 @@ try { } $expectedCount = [regex]::Match($receipt.checks.sulfurLoot, 'Dropped ([1-4]) ').Groups[1].Value if (!$receipt.checks.Contains('sulfurItem') -or $receipt.checks.sulfurItem -notmatch 'baseelectric:sulfur_powder' -or - $receipt.checks.sulfurItem -notmatch "Count: ${expectedCount}b") { + ($expectedCount -ne '1' -and $receipt.checks.sulfurItem -notmatch "count:\s*${expectedCount}\b")) { throw 'No live sulfur item stack matched the sulfur loot response.' } foreach ($type in @('laser', 'propeller')) { diff --git a/tools/verify-native-port.js b/tools/verify-native-port.js index 4c73fd7..2c86ccb 100644 --- a/tools/verify-native-port.js +++ b/tools/verify-native-port.js @@ -5,7 +5,8 @@ const { execFileSync } = require('node:child_process'); const { createHash } = require('node:crypto'); const root = path.resolve(__dirname, '..'); -const baseline = '013737d4cc41947e8b6fa42f4bf926a1fa5ab998'; +const baseline = '28dd438dde6898fcb6d6e1d17a62a4c0f527169e'; +const legacyTrackBaseline = '013737d4cc41947e8b6fa42f4bf926a1fa5ab998'; const git = (...args) => execFileSync('git', args, { cwd: root }); const old = file => git('show', baseline + ':' + file); const read = file => fs.readFileSync(path.join(root, file)); @@ -21,27 +22,26 @@ function check(name, run) { catch (error) { checks.push({name, pass: false, error: error.message}); } } -check('Exact Forge 47 and release identity', () => { +check('Exact Forge 50 and release identity', () => { const props = Object.fromEntries(read('gradle.properties').toString().split(/\r?\n/) .filter(line => /^[a-z][a-z_\d]*=/.test(line)).map(line => line.split(/=(.*)/s).slice(0, 2))); for (const [key, value] of Object.entries({ - minecraft_version: '1.20.1', forge_version: '47.4.10', mapping_channel: 'official', - mapping_version: '1.20.1', mcp_version: '20230612.114412', java_version: '17', - mod_id: 'baseelectric', mod_name: 'baseElectric', mod_version: '2.2.13.120011', - poweradvantage_version: '2.4.12.120011', basemetals_version: '3.1.2.120011', - orespawn_version: '4.1.0.120011', curseforge_project_id: '1783006', + minecraft_version: '1.20.6', forge_version: '50.2.0', mapping_channel: 'official', + mapping_version: '1.20.6', mcp_version: '20240429.135109', java_version: '21', + mod_id: 'baseelectric', mod_name: 'baseElectric', mod_version: '2.2.14.120061', + orespawn_version: '4.1.0.120061', curseforge_project_id: '1783006', cf_requirements: 'basepower,base-metals' })) assert.equal(props[key], value, key); - assert.deepEqual(json('src/main/resources/pack.mcmeta').pack, {pack_format:15, description:'baseElectric'}); + assert.deepEqual(json('src/main/resources/pack.mcmeta').pack, {pack_format:32, supported_formats:{min_inclusive:32,max_inclusive:41}, description:'baseElectric'}); const mods = read('src/main/resources/META-INF/mods.toml').toString(); - assert.match(mods, /modId="basepower"\s+mandatory=true\s+versionRange="\[2\.4\.12\.120011,3\.0\.0\)"/); - assert.match(mods, /modId="basemetals"\s+mandatory=false\s+versionRange="\[3\.1\.2\.120011,4\.0\.0\)"/); + assert.match(mods, /modId="basepower"\s+mandatory=true\s+versionRange="\[2\.4\.13\.120061,3\.0\.0\)"/); + assert.match(mods, /modId="basemetals"\s+mandatory=false\s+versionRange="\[3\.1\.2\.120061,4\.0\.0\)"/); }); function checkTrackModel(file, model) { assert.equal(model.render_type, 'minecraft:cutout', file + ' lacks its native cutout layer'); const { render_type, ...unchanged } = model; - assert.deepEqual(unchanged, JSON.parse(old(file)), file + ' changed beyond the render layer'); + assert.deepEqual(unchanged, JSON.parse(git('show', legacyTrackBaseline + ':' + file)), file + ' changed beyond the render layer'); } check('All 64 track states declare cutout without changing any geometry', () => { @@ -58,35 +58,40 @@ check('All 64 track states declare cutout without changing any geometry', () => check('Track audit rejects the old asset and a geometry mutation', () => { const file = assets + 'models/block/electric_track_ns.json'; - assert.throws(() => checkTrackModel(file, JSON.parse(old(file))), /lacks its native cutout layer/); + assert.throws(() => checkTrackModel(file, JSON.parse(git('show', legacyTrackBaseline + ':' + file))), /lacks its native cutout layer/); const mutated = json(file); mutated.elements[0].from[0]++; assert.throws(() => checkTrackModel(file, mutated), /changed beyond the render layer/); }); -check('Every other shipped resource and test fixture retains its accepted bytes', () => { +check('Unrelated shipped resources and fixtures retain accepted 1.20.1 bytes', () => { const resources = tracked.filter(file => /^src\/(main|test)\/resources\//.test(file)); - const exceptions = new Set(['src/main/resources/pack.mcmeta', 'src/main/resources/META-INF/mods.toml']); - for (const file of resources.filter(file => !exceptions.has(file) && !track(file))) { + const exceptions = new Set(['src/main/resources/pack.mcmeta', 'src/main/resources/META-INF/mods.toml', + assets + 'shaders/core/unshaded.vsh', assets + 'shaders/core/unshaded.json']); + for (const file of resources.filter(file => !exceptions.has(file) && !/\/data\/baseelectric\/(recipes|advancements\/recipes)\//.test(file))) { assert.equal(sha256(read(file)), sha256(old(file)), file); } const actual = fs.readdirSync(path.join(root, 'src'), {recursive:true, withFileTypes:true}) .filter(entry => entry.isFile()).map(entry => path.relative(root, path.join(entry.parentPath, entry.name)) .split(path.sep).join('/')).sort(); - assert.deepEqual(actual, [...tracked].sort(), 'Source and resource inventory'); + assert.deepEqual(actual, [...tracked, javaRoot.replace('main', 'test') + 'items/BatteryComponentTest.java', + javaRoot.replace('main', 'test') + 'items/LegacyBatteryDataTest.java', + javaRoot.replace('main', 'gametest') + 'gametest/ElectricGameTests.java', + 'src/gametest/resources/gameteststructures/empty.snbt'].sort(), + 'Source and resource inventory'); }); check('Migration and registration code keep their accepted IDs and compatibility paths', () => { for (const name of [ 'migration/ElectricLegacyMigrations.java', 'init/Blocks.java', 'init/Items.java', - 'init/Entities.java', 'init/GUI.java', 'init/OreSpawnWorldGen.java', 'recipe/RecipeConditions.java' + 'init/Entities.java', 'init/GUI.java', 'init/OreSpawnWorldGen.java' ]) { const file = javaRoot + name; assert.equal(sha256(read(file)), sha256(old(file)), file); } }); -check('All 96 inherited tests are still present, plus three new assertions', () => { +check('All 99 accepted tests are retained, plus three battery component tests', () => { const methods = value => [...value.toString().matchAll(/@Test\s+public void (\w+)\(/g)].map(m => m[1]); const files = tracked.filter(file => file.startsWith('src/test/java/') && file.endsWith('.java')); let inherited = 0; @@ -94,15 +99,37 @@ check('All 96 inherited tests are still present, plus three new assertions', () for (const file of files) { const current = read(file); const currentMethods = methods(current); - const priorMethods = methods(old(file)).map(name => name === 'resourcePackDeclaresTheNativeOneNineteenFourFormats' - ? 'resourcePackDeclaresTheNativeOneTwentyOneFormat' : name); + const priorMethods = methods(old(file)); for (const name of priorMethods) assert(currentMethods.includes(name), file + ' lost ' + name); assert.doesNotMatch(current.toString(), /@Ignore|Assume\.|assumeTrue\(|assumeFalse\(/, file); inherited += priorMethods.length; actual += currentMethods.length; } - assert.equal(inherited, 96); + assert.equal(inherited, 99); assert.equal(actual, 99); + assert.equal(methods(read(javaRoot.replace('main', 'test') + 'items/BatteryComponentTest.java')).length, 2); + assert.equal(methods(read(javaRoot.replace('main', 'test') + 'items/LegacyBatteryDataTest.java')).length, 1); +}); + + +check('Recipe results and guards retain their meaning under Forge 50 codecs', () => { + const files = tracked.filter(file => /\/data\/baseelectric\/recipes\/.*\.json$/.test(file)); + assert.equal(files.length, 58); + for (const file of files) { + const expected = JSON.parse(old(file)); + if (typeof expected.result === 'string') expected.result = {id: expected.result}; + else { + const {item, ...other} = expected.result; + expected.result = {id: item, ...other}; + } + if (expected.conditions) { + const conditions = expected.conditions; + delete expected.conditions; + expected['forge:condition'] = conditions.length === 1 ? conditions[0] + : {type:'forge:and', values:conditions}; + } + assert.deepEqual(json(file), expected, file); + } }); const report = {baseline, scope: 'Static source and resource comparison only', checks};