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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ jobs:
if-no-files-found: error
retention-days: 30
path: |
build/libs/OreSpawn-4.1.0.112021.jar
build/libs/OreSpawn-4.1.0.112021-sources.jar
build/libs/OreSpawn-4.1.0.112021-javadoc.jar
build/libs/OreSpawn-4.1.1.112021.jar
build/libs/OreSpawn-4.1.1.112021-sources.jar
build/libs/OreSpawn-4.1.1.112021-javadoc.jar
build/release/SHA256SUMS
CHANGELOG.txt

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Version 4.1.1.112021

* Keep existing provider settings when importing older ore files for the first
time, instead of replacing them with the older settings.
* Describe preserved settings as retained rather than verified in the upgrade
report. Invalid files are still checked by the normal provider loader.

Version 4.1.0.112021

* Clarify dimension-wide material controls and replace light-equivalent custom
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ It gives mods and modpacks one place to configure ores, deposit shapes, optional
rock strata and geomes, provider-owned underground fluid deposits, biome
palettes and world materials, flat bedrock, and bounded ore retrogen.

This branch builds target-qualified version `4.1.0.112021`: the OreSpawn 4.1.0
This branch builds target-qualified version `4.1.1.112021`: the OreSpawn 4.1.1
feature set for Minecraft 1.12.2 and Forge. It adds stable generation identity,
non-loading geology sampling, per-resource background control, existing-world
provider merge policy, an Ore Sources arbiter for equivalent provider ores, a
Expand Down
6 changes: 6 additions & 0 deletions docs/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ legacy-ID behaviour.
Migration is non-destructive. OreSpawn writes `config/orespawn-worldgen.json`
only when that target does not already exist and retains every source file.

An existing `config/<modid>-orespawn.json` override is also kept unchanged,
even when legacy files are imported for the first time. The upgrade report
records that the existing provider settings were retained, not validated.
An unfinished or invalid override is left for the normal provider validator;
migration does not replace it with defaults or older settings.

When `config/mineralogy-geomes.json` exists, OreSpawn imports the Mineralogy 6
profile directly, updates its schema marker, and records `migrated_from`.

Expand Down
2 changes: 1 addition & 1 deletion docs/VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Examples:
| Minecraft | Loader | Target | Example full OreSpawn version |
| --- | --- | ---: | --- |
| 1.10.2 | Forge | `110021` | `4.0.6.110021` |
| 1.12.2 | Forge | `112021` | `4.1.0.112021` |
| 1.12.2 | Forge | `112021` | `4.1.1.112021` |
| 1.13.2 | Forge | `113021` | `4.0.6.113021` |
| 1.20.6 | Forge | `120061` | `4.0.6.120061` |
| 1.21.11 | Forge | `121111` | `4.0.6.121111` |
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod_vendor=Minecraft Mod Development
mod_license=LGPL-2.1
mod_license_name=GNU Lesser General Public License, Version 2.1
mod_license_url=https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
mod_version=4.1.0.112021
mod_version=4.1.1.112021
mod_group=zone.moddev.mc.orespawn
mod_authors=SkyBlade1978, dshadowwolf, the MMD Team
mod_description=Configurable, provider-driven terrain, ore, and deposit generation.
Expand Down
8 changes: 4 additions & 4 deletions gradle/release/artifacts.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ tasks.register('verifyReleaseConfiguration') {
description = 'Validates the target-qualified release, API, schemas, reports, and publishing identity.'

doLast {
if (project.mod_version != '4.1.0.112021'
if (project.mod_version != '4.1.1.112021'
|| project.mod_group != expectedMavenGroup) {
throw new GradleException("Unexpected OreSpawn release version: ${project.mod_version}")
}
Expand All @@ -108,8 +108,8 @@ tasks.register('verifyReleaseConfiguration') {
'src/main/java/zone/moddev/mc/orespawn/worldgen/LegacyOs3ProfileMigration.java',
'README.md', 'CHANGELOG.txt'
].each { path ->
if (!file(path).getText('UTF-8').contains('4.1.0.112021')) {
throw new GradleException("Authoritative release location does not contain 4.1.0.112021: ${path}")
if (!file(path).getText('UTF-8').contains('4.1.1.112021')) {
throw new GradleException("Authoritative release location does not contain 4.1.1.112021: ${path}")
}
}
if (!file('docs/API.md').getText('UTF-8').contains('orespawn@[4.0.6,5.0.0)')) {
Expand Down Expand Up @@ -173,7 +173,7 @@ tasks.register('verifyReleaseArtifacts') {
}
['src/test/', 'src/biomeIntegrationTest/', 'src/migrationIntegrationTest/',
'src/clientIntegrationTest/', 'src/os1AbiFixture/', 'src/os3AbiFixture/',
'agent-notes/', 'surfaceprobe', 'migrationprobe', 'clientprobe',
'agent-notes/', 'AGENTS.md', 'AGENT.md', 'surfaceprobe', 'migrationprobe', 'clientprobe',
'codec-conflict/', 'LegacyApiConsumer', 'OreSourceEditorProbeBridge',
'org/junit/', 'org/mockito/', 'net/bytebuddy/'].each { forbidden ->
if (candidateZip.entries().any { it.name.contains(forbidden) }) {
Expand Down
19 changes: 15 additions & 4 deletions src/main/java/com/mcmoddev/orespawn/compat/LegacyOs3Bridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ private static void migrateConfigDirectory(Path configDirectory) {
}
for (Map.Entry<String, JsonObject> provider : providers.entrySet()) {
try {
writeAtomicIfChanged(configDirectory.resolve(provider.getKey() + "-orespawn.json"), provider.getValue());
writeProviderIfAbsent(configDirectory.resolve(provider.getKey() + "-orespawn.json"), provider.getValue());
} catch (IOException failure) {
REPORT.add("provider_write_failed=" + provider.getKey() + ":" + failure.getClass().getSimpleName());
LOGGER.error("Could not write migrated OS3 provider {}", provider.getKey(), failure);
Expand Down Expand Up @@ -792,6 +792,16 @@ private static int metadata(String block, String state) {
return 0;
}

static void writeProviderIfAbsent(Path destination, JsonObject value) throws IOException {
// An existing OS4 file is a pack's choice, even on its first legacy import.
if (Files.isRegularFile(destination)) {
REPORT.add("provider_preserved=" + destination.getFileName());
return;
}

writeAtomicIfChanged(destination, value);
}

private static void writeAtomicIfChanged(Path destination, JsonObject value) throws IOException {
byte[] data = (GSON.toJson(value) + System.lineSeparator()).getBytes(StandardCharsets.UTF_8);
if (Files.isRegularFile(destination) && Arrays.equals(Files.readAllBytes(destination), data)) {
Expand Down Expand Up @@ -833,7 +843,8 @@ private static void writeHumanUpgradeReport(Path destination) throws IOException
String lower = row.toLowerCase(java.util.Locale.ROOT);
if (lower.startsWith("config_source=") || lower.startsWith("resource_loaded=")
|| lower.startsWith("config_registered=")) sources.add(row);
if ((lower.startsWith("provider_written=") || lower.startsWith("provider_unchanged="))
if ((lower.startsWith("provider_written=") || lower.startsWith("provider_unchanged=")
|| lower.startsWith("provider_preserved="))
&& !lower.contains("migration-report")) providers.add(row);
if (lower.contains("_failed=") || lower.contains("_rejected=")
|| lower.contains("_ignored=") || lower.contains("_unresolved=")
Expand All @@ -842,12 +853,12 @@ private static void writeHumanUpgradeReport(Path destination) throws IOException
}
}
List<String> lines = new ArrayList<>();
lines.add("OreSpawn 4.1.0.112021 Upgrade Report");
lines.add("OreSpawn 4.1.1.112021 Upgrade Report");
lines.add("================================");
lines.add("");
lines.add("RESULT: Legacy OreSpawn configuration was consumed and translated for OS4.");
lines.add("- Legacy sources read: " + sources.size());
lines.add("- OS4 provider files written or verified: " + providers.size());
lines.add("- OS4 provider files written or retained: " + providers.size());
lines.add("- Unique items requiring review: " + warnings.size());
lines.add("");
lines.add(warnings.isEmpty()
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/zone/moddev/mc/orespawn/OreSpawn.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class OreSpawn {

public static final String MODID = "orespawn";
public static final String NAME = "OreSpawn";
public static final String VERSION = "4.1.0.112021";
public static final String VERSION = "4.1.1.112021";

private static final Logger LOGGER = LogManager.getLogger();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private static void writeUpgradeReport(Path worldRoot, Path configDirectory,
Path report = worldRoot.resolve("serverconfig/orespawn-upgrade-report.txt");
List<String> missing = missingBlocks(igneous, metamorphic, sedimentary);
List<String> lines = new ArrayList<>();
lines.add("OreSpawn 4.1.0.112021 Upgrade Report");
lines.add("OreSpawn 4.1.1.112021 Upgrade Report");
lines.add("================================");
lines.add("");
lines.add("RESULT: Existing Mineralogy " + identity.version + " world detected.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private static void writeInitialUpgradeReport(Path configDirectory,
boolean forceRetrogen, boolean flatBedrock, boolean retrogenBedrock,
int bedrockLayers) throws IOException {
String newline = System.lineSeparator();
String text = "OreSpawn 4.1.0.112021 Upgrade Report" + newline
String text = "OreSpawn 4.1.1.112021 Upgrade Report" + newline
+ "================================" + newline + newline
+ "RESULT: Legacy OreSpawn settings were imported into the OS4 profile." + newline
+ "- Manage vanilla ores: " + manageVanilla + newline
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -43,6 +44,99 @@ static void bootstrapMinecraft() {
Forge14TestBootstrap.registerVanilla();
}

@Test
void keepsAnExistingProviderOverrideDuringLegacyImport() throws Exception {
Path destination = temporary.resolve("basemetals-orespawn.json");
String existing = "{ \"schema_version\": 5, \"provider_modid\": \"basemetals\", \"provider_revision\": 1 }\n";
Files.write(destination, existing.getBytes(StandardCharsets.UTF_8));

LegacyOs3Bridge.writeProviderIfAbsent(destination, new JsonObject());

assertEquals(existing, new String(Files.readAllBytes(destination), StandardCharsets.UTF_8));
assertFalse(Files.exists(temporary.resolve("basemetals-orespawn.json.os3-backup")));
assertTrue(LegacyOs3Bridge.reportForTests().contains("provider_preserved=basemetals-orespawn.json"));
}

@Test
void leavesAMalformedOverrideForTheNormalProviderValidator() throws Exception {
Path destination = temporary.resolve("basemetals-orespawn.json");
String existing = "{ unfinished user edit";
Files.write(destination, existing.getBytes(StandardCharsets.UTF_8));

LegacyOs3Bridge.writeProviderIfAbsent(destination, new JsonObject());

assertEquals(existing, new String(Files.readAllBytes(destination), StandardCharsets.UTF_8));
}

@Test
void writesAnImportedProviderOnlyWhenNoOverrideExists() throws Exception {
Path destination = temporary.resolve("basemetals-orespawn.json");
JsonObject imported = new JsonObject();
imported.addProperty("provider_modid", "basemetals");
imported.addProperty("provider_revision", 1);

LegacyOs3Bridge.writeProviderIfAbsent(destination, imported);
String first = new String(Files.readAllBytes(destination), StandardCharsets.UTF_8);
assertEquals(imported, new JsonParser().parse(first));

imported.addProperty("provider_revision", 9);
LegacyOs3Bridge.writeProviderIfAbsent(destination, imported);
assertEquals(first, new String(Files.readAllBytes(destination), StandardCharsets.UTF_8));
}

@Test
void keepsAnExistingProviderDuringTheFirstImportAndReload() throws Exception {
LegacyOs3Bridge.resetProgrammaticForTests("overridefixture");
Path legacy = temporary.resolve("orespawn3");
Files.createDirectories(legacy);
Files.write(legacy.resolve("overridefixture.json"),
"{\"spawns\":{}}".getBytes(StandardCharsets.UTF_8));
Path destination = temporary.resolve("orespawn-orespawn.json");
String existing = "{ \"schema_version\": 5, \"provider_modid\": \"orespawn\", \"provider_revision\": 9 }\n";
Files.write(destination, existing.getBytes(StandardCharsets.UTF_8));

migrateLegacyDirectory(temporary);

assertEquals(existing, new String(Files.readAllBytes(destination), StandardCharsets.UTF_8));
assertFalse(Files.exists(temporary.resolve("orespawn-orespawn.json.os3-backup")));
Path report = temporary.resolve("orespawn-upgrade-report.txt");
String firstReport = new String(Files.readAllBytes(report), StandardCharsets.UTF_8);
assertTrue(firstReport.contains("provider_preserved=orespawn-orespawn.json"));

migrateLegacyDirectory(temporary);

assertEquals(existing, new String(Files.readAllBytes(destination), StandardCharsets.UTF_8));
assertEquals(firstReport, new String(Files.readAllBytes(report), StandardCharsets.UTF_8));
}

@Test
void describesAnUnvalidatedOverrideAsRetainedRatherThanVerified() throws Exception {
LegacyOs3Bridge.resetProgrammaticForTests("reportfixture");
Path legacy = temporary.resolve("orespawn3");
Files.createDirectories(legacy);
Files.write(legacy.resolve("reportfixture.json"),
"{\"spawns\":{}}".getBytes(StandardCharsets.UTF_8));
Path destination = temporary.resolve("orespawn-orespawn.json");
String existing = "{ unfinished user edit";
Files.write(destination, existing.getBytes(StandardCharsets.UTF_8));

migrateLegacyDirectory(temporary);

assertEquals(existing, new String(Files.readAllBytes(destination), StandardCharsets.UTF_8));
String report = new String(Files.readAllBytes(
temporary.resolve("orespawn-upgrade-report.txt")), StandardCharsets.UTF_8);
assertTrue(report.contains("OS4 provider files written or retained: 1"));
assertFalse(report.contains("written or verified"));
assertTrue(report.contains("provider_preserved=orespawn-orespawn.json"));
}

private static void migrateLegacyDirectory(Path directory) throws Exception {
Method migration = LegacyOs3Bridge.class.getDeclaredMethod("migrateConfigDirectory", Path.class);
migration.setAccessible(true);
migration.invoke(null, directory);
}


@Test
void translatesAllOs3PatternsSelectorsWeightsMetadataAndFlags() throws Exception {
Path legacy = temporary.resolve("orespawn3");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void discoversLoadedNativeLegacyUiOnlyInactiveAndRejectedIntegrations() {
"directory_ui_only", parent -> new GuiScreen() { });

List<LoadedMod> loaded = Arrays.asList(
new LoadedMod("orespawn", "MMD OreSpawn", "4.1.0.112021"),
new LoadedMod("orespawn", "MMD OreSpawn", "4.1.1.112021"),
new LoadedMod("directory_realistic", "Realistic Deposits", "0.1.0.110021"),
new LoadedMod("directory_base", "Base Metals", "2.5.0-beta5"),
new LoadedMod("directory_mineralogy", "Mineralogy", "6.0.2.110021"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package zone.moddev.mc.orespawn.documentation;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -38,6 +39,7 @@ void exportsCompleteGuideAndDoesNotOverwriteExistingFiles() throws Exception {
"runtime export differs for " + relative);
}
assertTrue(Files.isRegularFile(temporaryDirectory.resolve("README.md")));
assertFalse(Files.exists(temporaryDirectory.resolve("AGENTS.md")));
assertTrue(Files.isRegularFile(temporaryDirectory.resolve("DEVELOPER_GUIDE.md")));
assertTrue(Files.isRegularFile(temporaryDirectory.resolve("BIOMES.md")));
assertTrue(Files.isRegularFile(temporaryDirectory.resolve("examples/examplemod-orespawn.json")));
Expand Down
Loading