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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ jobs:
- name: Build with Gradle
env:
BUILD_NUMBER: ${{ github.run_number }}
run: ./gradlew assemble

- name: Run tests
run: ./gradlew check
run: ./gradlew clean build

- name: Publish Test Report
uses: mikepenz/action-junit-report@v4
Expand Down
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
### Base Metals 4.0.0.121012 (in development)
### Base Metals 4.0.1.121012

- Let compatible mods join the legacy world conversion before Minecraft fixes old chunk and item data.
- Keep basePower, baseSteam and baseElectric machine state, inventories and equipment when upgrading old Advantage worlds.
- Skip legacy conversion for modern worlds and keep backups and source registry snapshots for genuine old saves.
- Add native NeoForge regression tests for the shared migration hook and modern-world safety checks.
- Keep oversized external chunks writable during conversion and leave original region backups untouched.
- Recover player data after an interrupted startup, and run companion fixes for dedicated-server players too.
- Keep host recovery available if region conversion finishes before the first modern world save.
- End legacy terrain protection after the current world has upgraded, while retaining its old registry map.
- Keep ordinary CI builds independent of release tags and support resource tests started from an IDE.

### Base Metals 4.0.0.121012

- Port Base Metals to Minecraft 1.21.1 and NeoForge.
- Restore recipe-book unlocks and armour advancements in the new data-pack folders.
Expand Down
37 changes: 30 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,41 @@ shields, bows, crossbows, arrows, and bolts. The mod also includes Crack
Hammers, scythes, metal anvils, the human detector, villager trades,
advancements, and structure loot.

This is the Minecraft 1.21.1 NeoForge port, `4.0.0.121012`. It includes raw
This is the Minecraft 1.21.1 NeoForge port, `4.0.1.121012`. It includes raw
metals, ore texture overlays and High/Low Fantasy modes. Existing Base Metals items and blocks keep
their registry IDs. OreSpawn handles ore generation; MMDLib and Additional Loot
Tables are no longer needed.
their registry IDs. OreSpawn handles ore generation. MMDLib supplies the shared
materials, crushing recipes, anvils and equipment effects used by this version.
Additional Loot Tables is not needed.

## Requirements

- Minecraft `1.21.1`
- NeoForge `21.1.247` or newer in the Minecraft 1.21.1 line
- Java 21
- MMDLib `2.0.1.121012+Neo` on both client and server
- OreSpawn `[4.0.16.121012,5.0.0)` for Minecraft 1.21.1 NeoForge on both client and server

This version builds against OreSpawn `4.0.16.121012`. Put
`BaseMetals-4.0.0.121012.jar` and a compatible OreSpawn JAR in the `mods`
directory. MMDLib and Additional Loot Tables must not be carried forward from
an older installation. Mineralogy is optional.
`basemetals-4.0.1.121012.jar`, the matching MMDLib jar and a compatible OreSpawn
jar in the `mods` directory. Do not carry older Forge or 1.12 MMDLib jars
forward. Additional Loot Tables is not required. Mineralogy is optional.

### Upgrading Existing Worlds

Back up the whole save before upgrading. This patch adds a shared conversion
hook so basePower and its expansions can preserve old Advantage machine data
before Minecraft converts legacy chunks and items. Existing Base Metals registry
names stay unchanged. Modern saves bypass the old-world conversion path.

The converter keeps original regions and player files under
`basemetals-1.12-region-backup`. Before the loader rewrites old single-player
data, it saves a player snapshot there so an interrupted first load can resume.
The snapshot is not reapplied after the first modern world save. Finishing
region conversion alone does not discard recovery before that save. Keep the
backups with the world until you have checked
the upgrade. Large external chunk files are handled by Minecraft's own region
writer. The retained registry map does not keep world-generation protection
enabled on an already-upgraded world.

## Materials and gameplay

Expand Down Expand Up @@ -195,7 +214,11 @@ the generated resources with the source changes. Ore models use KiriCattus'
transparent overlays over vanilla textures,
so resource packs can replace the surrounding stone, netherrack or end stone.

The port regression checks are separate from the normal build. Run them with:
`./gradlew check` runs the native resource and migration regression tests as part
of the normal build. These include interrupted upgrades, dedicated-server
players, large external chunks and unchanged backups.

The additional port GameTests can be run with:

```text
./gradlew -I tools/verification/port-checks.init.gradle portTest runPortGameTestServer
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ var generateModMetadata = tasks.register("generateModMetadata", ProcessResources
sourceSets.main.resources.srcDir generateModMetadata
// To avoid having to run "generateModMetadata" manually, make it run on every project reload
neoForge.ideSyncTask generateModMetadata
apply from: 'gradle/advantage-migration-tests.gradle'

tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Project
mod_version = 4.0.0.121012
mod_version = 4.0.1.121012
mod_name = MMD Base Metals
mod_id=basemetals
mod_archive_name = basemetals
Expand Down
19 changes: 19 additions & 0 deletions gradle/advantage-migration-tests.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// The migration extension is qualified in the native NeoForge test runtime.
sourceSets.test.java.srcDir 'src/verificationTest/java'
neoForge.unitTest {
enable()
testedMod = neoForge.mods.basemetals
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.11.4'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.11.4'
}
tasks.named('test', Test) {
useJUnitPlatform()
maxParallelForks = 1
maxHeapSize = '2G'
jvmArgs '-XX:ActiveProcessorCount=4'
workingDir projectDir
systemProperty 'basemetals.test.projectDir', projectDir.absolutePath
testLogging { events 'failed', 'skipped'; exceptionFormat = 'full' }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package zone.moddev.mc.basemetals.api.migration;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.state.BlockState;
import zone.moddev.mc.basemetals.migration.Legacy112WorldMigrator;

/**
* Companion callbacks run before vanilla consumes legacy mod data. Register once
* during mod setup. Callbacks run serially during startup and must tolerate a
* retry after an interrupted upgrade. Do not access live worlds from a callback.
*/
public interface Legacy112MigrationExtension {
enum Payload { CHUNK, PLAYER }

/** Mutate legacy data before snapshotting; report whether anything changed. */
default boolean prepareData(CompoundTag tag, int dataVersion, Payload payload) { return false; }

default void beforeChunkFlattening(CompoundTag chunk) { }

/**
* Called for the embedded single-player host and legacy playerdata files.
* Result uses the 1.20.1 item schema; component conversion runs afterwards.
*/
default void afterPlayerFlattening(CompoundTag preparedSource, CompoundTag result) { }

/** Return null for an unowned ID; never return air for an owned legacy block. */
default BlockState decodeBlockState(ResourceLocation legacyId, int metadata) { return null; }

static void register(ResourceLocation id, Legacy112MigrationExtension extension) {
Legacy112WorldMigrator.registerExtension(id, extension);
}
}
Loading
Loading