Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
36 changes: 30 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:
contents: read

concurrency:
group: poweradvantage-1.12-${{ github.workflow }}-${{ github.ref }}
group: basepower-1.12-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
Expand All @@ -26,6 +26,14 @@ jobs:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Check out pinned OreSpawn
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
repository: MinecraftModDevelopmentMods/OreSpawn
ref: 72205b9bb6bfff17cf69715c0d5bd4d2efd3b148
path: .ci-dependencies/OreSpawn
persist-credentials: false

- name: Install Java 8 toolchain
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
Expand All @@ -41,6 +49,21 @@ jobs:
- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6

- name: Build pinned OreSpawn development jar
id: orespawn
shell: bash
run: |
set -euo pipefail
dependency="$GITHUB_WORKSPACE/.ci-dependencies/OreSpawn"
chmod +x "$dependency/gradlew"
(
cd "$dependency"
./gradlew deobfJar --no-daemon --stacktrace
)
jar="$dependency/build/libs-dev/OreSpawn-4.1.3.112021-deobf.jar"
test -f "$jar"
echo "jar=$jar" >> "$GITHUB_OUTPUT"

- name: Make the wrapper executable
run: chmod +x ./gradlew

Expand All @@ -56,26 +79,27 @@ jobs:
./gradlew clean check build javadoc verifyReleaseDependencies verifyReleaseArtifacts
writeReleaseChecksums verifyEclipseProductionClasspath
-PrebornCoreVerificationRepository=${{ steps.reborncore.outputs.repository }}
-PoreSpawnDeobfJar=${{ steps.orespawn.outputs.jar }}
--no-daemon --stacktrace

- name: Upload audited release candidate
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: PowerAdvantage-1.12.2-${{ github.sha }}
name: basePower-1.12.2-${{ github.sha }}
if-no-files-found: error
retention-days: 30
path: |
build/libs/PowerAdvantage-2.4.1.112021.jar
build/libs/PowerAdvantage-2.4.1.112021-sources.jar
build/libs/PowerAdvantage-2.4.1.112021-javadoc.jar
build/libs/basePower-2.4.4.112021.jar
build/libs/basePower-2.4.4.112021-sources.jar
build/libs/basePower-2.4.4.112021-javadoc.jar
build/release/SHA256SUMS
CHANGELOG.txt

- name: Upload diagnostics on failure
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: PowerAdvantage-1.12.2-diagnostics-${{ github.sha }}
name: basePower-1.12.2-diagnostics-${{ github.sha }}
if-no-files-found: ignore
retention-days: 14
path: |
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ jobs:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Check out pinned OreSpawn
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
repository: MinecraftModDevelopmentMods/OreSpawn
ref: 72205b9bb6bfff17cf69715c0d5bd4d2efd3b148
path: .ci-dependencies/OreSpawn
persist-credentials: false

- name: Install Java 8 toolchain
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
Expand All @@ -41,6 +49,21 @@ jobs:
- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6

- name: Build pinned OreSpawn development jar
id: orespawn
shell: bash
run: |
set -euo pipefail
dependency="$GITHUB_WORKSPACE/.ci-dependencies/OreSpawn"
chmod +x "$dependency/gradlew"
(
cd "$dependency"
./gradlew deobfJar --no-daemon --stacktrace
)
jar="$dependency/build/libs-dev/OreSpawn-4.1.3.112021-deobf.jar"
test -f "$jar"
echo "jar=$jar" >> "$GITHUB_OUTPUT"

- name: Stage exact RebornCore compile API
id: reborncore
run: |
Expand All @@ -57,6 +80,7 @@ jobs:
run: |
chmod +x ./gradlew
./gradlew clean classes --rerun-tasks --no-build-cache --no-daemon --stacktrace \
-PoreSpawnDeobfJar="${{ steps.orespawn.outputs.jar }}" \
-PrebornCoreVerificationRepository=${{ steps.reborncore.outputs.repository }}

- name: Analyze
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-on-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ permissions:
contents: read

concurrency:
group: poweradvantage-release-tag-${{ github.ref_name }}
group: basepower-release-tag-${{ github.ref_name }}
cancel-in-progress: false

jobs:
validate-release-tag:
name: Validate tag for manual release confirmation
if: github.repository == 'MinecraftModDevelopmentMods/PowerAdvantage'
if: github.repository == 'MinecraftModDevelopmentMods/basePower'
runs-on: ubuntu-latest
timeout-minutes: 10

Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
Unreleased test-coverage repairs for 1.12.2
2.4.4.112021 - basePower for Minecraft 1.12.2

- Bring basePower to Forge 1.12.2. Upgrade worlds from the original Advantage mods or the 1.10.2 base mods, keeping blocks, items, fluids and machine contents.
- Preserve the world-generation settings for oil, sulfur and lithium when moving to OreSpawn 4 on 1.12.2.
- Keep the saved MMDLib crusher recipe IDs when replacing the old 1.12.2 Advantage mods.
- Fix the still so pipes fill the input tank and can only drain the output. Crude oil from Mineralogy also works in the still.

Earlier 1.12.2 test-coverage repairs

- Restore the missing carbon-dust recipe name from registered coal and charcoal powders, without replacing existing entries or changing recipe amounts.
- Enable Forge's universal bucket during mod construction so oil buckets work without another mod enabling them first.
Expand Down
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# PowerAdvantage
# basePower for Minecraft 1.12.2

Power Advantage provides shared power, fluid, and item transport systems for its Minecraft 1.12.2 expansion mods.
basePower continues DrCyano's Power Advantage. It adds conveyors, filters, fluid plumbing and the shared systems used by baseSteam and baseElectric. The 1.12.2 build uses Forge 14.23.5.2859 and Java 8.

The [test coverage backport notes](TEST-COVERAGE-BACKPORT.md#final-recorded-candidate) record the final machine, restart, control, partial-network, GUI, endurance, connected-world and reproducibility results alongside exact candidate hashes. The bounded legacy checks pass; the recipe progression graph is still partial. Earlier failures, modern follow-up findings and manual-testing limits are kept in the notes. This is not an all-machines or all-worlds guarantee.
## Moving an existing world

You can upgrade from the original Advantage mods or the base mods on 1.10.2. If you're already using the old Advantage mods on 1.12.2, you can replace them too. Back up your world and config, replace the old mods together, then try the upgrade on a copy. Save, close Minecraft completely and reopen the copy before moving your main world.

Use Forge 14.23.5.2859 or newer, with the 1.12.2 builds of Base Metals, MMDLib and MMD OreSpawn 4.1.3 or newer in the 4.x line. Existing MMDLib crusher recipes keep their saved IDs. If Forge still warns about missing entries, cancel and check what's missing before proceeding. See the [world upgrade guide](docs/1.12-upgrade.md).

[CurseForge](https://www.curseforge.com/minecraft/mc-mods/basepower) | [Player wiki](https://github.com/MinecraftModDevelopmentMods/basePower/wiki)

## Building Minecraft 1.12.2

Expand All @@ -20,4 +26,6 @@ For Eclipse, import the repository as an existing Gradle project and run:
gradlew.bat cleanEclipse verifyEclipseProductionClasspath
```

Base Metals and OreSpawn remain required distribution dependencies but are deliberately absent from the compile classpath. Optional RF and RebornCore integrations compile against SHA-256-pinned API inputs and are not bundled or added to normal development launches. CI stages the exact historical RebornCore Maven release because the later CurseForge archive with the same version has different contents.
Build the pinned OreSpawn 4.1.3.112021 development jar first, or pass `-PoreSpawnDeobfJar=<path>`. CI builds the exact source in `gradle.properties`. Base Metals is a distribution dependency, not a compile dependency. Optional RF and RebornCore APIs are compile-only and are not bundled. CI stages the exact historical RebornCore Maven artifact; the later CurseForge archive with the same version has different contents.

See [Checking a base workshop upgrade](docs/1.12-validation.md) for the current test procedure. The [test coverage notes](TEST-COVERAGE-BACKPORT.md) describe the preceding Advantage build.
62 changes: 40 additions & 22 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ tasks.register('clientResourceProbeJar', Jar) {

group = project.mod_group
version = project.mod_version
base.archivesName = 'PowerAdvantage'
base.archivesName = 'basePower'

def versionParts = project.mod_version.toString().tokenize('.')
if (versionParts.size() != 4 || !versionParts.every { it ==~ /\d+/ }) {
Expand Down Expand Up @@ -181,6 +181,12 @@ repositories {
}

def rfApiJar = file('libs/RF-API.jar')
// Use the matching OreSpawn 1.12 build; CI may stage it outside the sibling checkout.
def oreSpawnJar = file(providers.gradleProperty('oreSpawnDeobfJar').getOrElse(
"../../../MinecraftMineralogy/OS112/OreSpawn/build/libs-dev/OreSpawn-${project.orespawn_version}-deobf.jar"))
if (!oreSpawnJar.isFile()) {
throw new GradleException("Missing OreSpawn development jar: ${oreSpawnJar}. Build the pinned source or set -PoreSpawnDeobfJar=<path>.")
}
def usingStagedRebornCore = providers.gradleProperty('rebornCoreVerificationRepository').isPresent()
def rebornCoreCoordinate = usingStagedRebornCore
? "curse.maven:reborncore-${project.reborncore_curse_project_id}:${project.reborncore_curse_file_id}"
Expand All @@ -197,6 +203,7 @@ dependencies {
// but do not package or launch PowerAdvantage with the provider mods.
compileOnly files(rfApiJar)
compileOnly rebornCoreCoordinate
implementation files(oreSpawnJar)
}

tasks.named('processResources', ProcessResources) {
Expand Down Expand Up @@ -326,7 +333,7 @@ tasks.register('verifyReleaseConfiguration') {
group = 'verification'
description = 'Validates release identity, target metadata, and optional integration policy.'
doLast {
if (project.mod_version != '2.4.1.112021') {
if (project.mod_version != '2.4.4.112021') {
throw new GradleException("Unexpected PowerAdvantage release version: ${project.mod_version}")
}
if (project.minecraft_version != '1.12.2'
Expand All @@ -341,10 +348,10 @@ tasks.register('verifyReleaseConfiguration') {
|| project.gradle_java_version != '17') {
throw new GradleException('Unexpected release dispatcher target metadata')
}
if (project.mod_id != 'poweradvantage'
|| project.group.toString() != 'com.mcmoddev.poweradvantage'
|| base.archivesName.get() != 'PowerAdvantage'
|| project.curseforge_project_id != '240982') {
if (project.mod_id != 'basepower'
|| project.group.toString() != 'zone.moddev.mc.basepower'
|| base.archivesName.get() != 'basePower'
|| project.curseforge_project_id != '1780140') {
throw new GradleException('Unexpected Forge, Maven, archive, or CurseForge identity')
}
if (project.cf_requirements != 'base-metals,mmd-orespawn'
Expand All @@ -361,17 +368,17 @@ tasks.register('verifyReleaseConfiguration') {
throw new GradleException('Unexpected RebornCore compile API identity')
}
String mainSource = file(
'src/main/java/com/mcmoddev/poweradvantage/PowerAdvantage.java').getText('UTF-8')
if (!mainSource.contains('MODID = "poweradvantage"')
|| !mainSource.contains('VERSION = "2.4.1.112021"')
|| !mainSource.contains('dependencies = "after:basemetals"')) {
'src/main/java/zone/moddev/mc/basepower/PowerAdvantage.java').getText('UTF-8')
if (!mainSource.contains('MODID = "basepower"')
|| !mainSource.contains('VERSION = "2.4.4.112021"')
|| !mainSource.contains('required-before:orespawn@[4.1.3,5.0.0)')) {
throw new GradleException('PowerAdvantage source identity or optional BaseMetals policy changed')
}
if (!file('src/main/java/cyano/poweradvantage/api/PoweredEntity.java').isFile()) {
throw new GradleException('Legacy cyano.poweradvantage.api compatibility surface is missing')
}
String entitySource = file(
'src/main/java/com/mcmoddev/poweradvantage/init/Entities.java').getText('UTF-8')
'src/main/java/zone/moddev/mc/basepower/init/Entities.java').getText('UTF-8')
[
'tileentity.pipe_terminal', 'tileentity.fluid_drain',
'tileentity.fluid_discharge', 'tileentity.fluid_storage_tank',
Expand All @@ -386,8 +393,8 @@ tasks.register('verifyReleaseConfiguration') {
}
def metadata = new JsonSlurper().parse(file('src/main/resources/mcmod.info'))
def mod = metadata instanceof List ? metadata.first() : metadata
if (mod.modid != 'poweradvantage') {
throw new GradleException('Source mcmod.info does not use the stable poweradvantage mod id')
if (mod.modid != 'basepower') {
throw new GradleException('Source mcmod.info does not use the stable basepower mod id')
}
}
}
Expand All @@ -397,6 +404,11 @@ tasks.register('verifyReleaseDependencies') {
description = 'Resolves and audits Forge plus the exact optional compile APIs.'
dependsOn tasks.named('verifyReleaseConfiguration')
doLast {
def oreSpawnHash = MessageDigest.getInstance('SHA-256').digest(oreSpawnJar.bytes)
.encodeHex().toString().toUpperCase(Locale.ROOT)
if (oreSpawnHash != project.orespawn_deobf_sha256) {
throw new GradleException("Unexpected OreSpawn development artifact: ${oreSpawnHash}")
}
if (!rfApiJar.isFile()) {
throw new GradleException("Missing tracked RF API jar: ${rfApiJar}")
}
Expand Down Expand Up @@ -453,7 +465,10 @@ tasks.register('verifyReleaseDependencies') {
|| runtimeFiles.contains(rebornCoreJar.canonicalFile)) {
throw new GradleException('Optional RF or RebornCore API leaked onto runtimeClasspath')
}
List<String> forbiddenRuntimeMods = runtimeFiles.collect { it.name.toLowerCase(Locale.ROOT) }
if (!compileFiles.contains(oreSpawnJar.canonicalFile) || !runtimeFiles.contains(oreSpawnJar.canonicalFile)) {
throw new GradleException('Pinned OreSpawn is missing from the development classpath')
}
List<String> forbiddenRuntimeMods = (runtimeFiles - oreSpawnJar.canonicalFile).collect { it.name.toLowerCase(Locale.ROOT) }
.findAll { name ->
name.contains('basemetals') || name.contains('orespawn')
|| name.contains('tesla') || name.contains('reborncore')
Expand Down Expand Up @@ -503,16 +518,16 @@ tasks.register('verifyReleaseArtifacts') {
new ZipFile(mainJar).withCloseable { zip ->
List<String> names = zip.entries().collect { it.name }
['mcmod.info', 'pack.mcmeta',
'com/mcmoddev/poweradvantage/PowerAdvantage.class',
'zone/moddev/mc/basepower/PowerAdvantage.class',
'cyano/poweradvantage/api/PoweredEntity.class',
'assets/poweradvantage/lang/en_us.lang'].each { required ->
'assets/basepower/lang/en_us.lang'].each { required ->
if (!names.contains(required)) {
throw new GradleException("Release jar is missing ${required}")
}
}
['agent-notes/', '.codex/', 'src/test/', 'fernflower_abstract_parameter_names.txt',
'cofh/api/', 'reborncore/api/', 'cyano/basemetals/', 'com/mcmoddev/lib/',
'net/minecraft/', 'net/minecraftforge/'].each { forbidden ->
'net/minecraft/', 'net/minecraftforge/', 'zone/moddev/mc/orespawn/', 'com/mcmoddev/orespawn/'].each { forbidden ->
if (names.any { it.contains(forbidden) }) {
throw new GradleException("Release jar contains forbidden entry matching ${forbidden}")
}
Expand Down Expand Up @@ -546,7 +561,7 @@ tasks.register('verifyReleaseArtifacts') {
}

new ZipFile(new File(libs, expectedReleaseFiles.get()[1])).withCloseable { sourceZip ->
if (sourceZip.getEntry('com/mcmoddev/poweradvantage/PowerAdvantage.java') == null
if (sourceZip.getEntry('zone/moddev/mc/basepower/PowerAdvantage.java') == null
|| sourceZip.getEntry('cyano/poweradvantage/api/PoweredEntity.java') == null) {
throw new GradleException('Sources jar is missing implementation or legacy API sources')
}
Expand All @@ -564,6 +579,9 @@ tasks.register('writeReleaseChecksums') {
description = 'Writes SHA-256 checksums for the audited release jars.'
dependsOn tasks.named('verifyReleaseArtifacts')
def outputFile = layout.buildDirectory.file('release/SHA256SUMS')
inputs.files(expectedReleaseFiles.map { names ->
names.collect { layout.buildDirectory.file("libs/${it}").get().asFile }
})
outputs.file(outputFile)
doLast {
File output = outputFile.get().asFile
Expand Down Expand Up @@ -645,17 +663,17 @@ publishing {
pom {
name = 'Power Advantage'
description = project.mod_description
url = 'https://github.com/MinecraftModDevelopmentMods/PowerAdvantage'
url = 'https://github.com/MinecraftModDevelopmentMods/basePower'
licenses {
license {
name = 'GNU Lesser General Public License, Version 3'
url = 'https://www.gnu.org/licenses/lgpl-3.0.txt'
}
}
scm {
connection = 'scm:git:https://github.com/MinecraftModDevelopmentMods/PowerAdvantage.git'
developerConnection = 'scm:git:ssh://git@github.com/MinecraftModDevelopmentMods/PowerAdvantage.git'
url = 'https://github.com/MinecraftModDevelopmentMods/PowerAdvantage'
connection = 'scm:git:https://github.com/MinecraftModDevelopmentMods/basePower.git'
developerConnection = 'scm:git:ssh://git@github.com/MinecraftModDevelopmentMods/basePower.git'
url = 'https://github.com/MinecraftModDevelopmentMods/basePower'
}
}
}
Expand Down
Loading
Loading