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.110021.jar
build/libs/OreSpawn-4.1.0.110021-sources.jar
build/libs/OreSpawn-4.1.0.110021-javadoc.jar
build/libs/OreSpawn-4.1.1.110021.jar
build/libs/OreSpawn-4.1.1.110021-sources.jar
build/libs/OreSpawn-4.1.1.110021-javadoc.jar
build/release/SHA256SUMS
CHANGELOG.txt

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

* Keep existing provider settings when importing older OS1 or OS3 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.
* Keep the documentation index in docs/README.md and stop bundling the old
duplicate guide.

Version 4.1.0.110021

* 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.110021`: the OreSpawn 4.1.0
This branch builds target-qualified version `4.1.1.110021`: the OreSpawn 4.1.1
feature set for Minecraft 1.10.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 and
Expand Down
8 changes: 2 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ tasks.register('verifyDocumentationParity') {
dependsOn tasks.named('processResources')
doLast {
List<File> tracked = trackedDocumentationFiles()
if (tracked.size() != 21) {
throw new GradleException("Expected 21 tracked documentation files, found ${tracked.size()}")
if (tracked.size() != 20) {
throw new GradleException("Expected 20 tracked documentation files, found ${tracked.size()}")
}
tracked.each { File source ->
String relative = documentationRelativePath(source)
Expand All @@ -213,10 +213,6 @@ tasks.named('processResources', ProcessResources) {
filesMatching('mcmod.info') {
expand version: project.version, mcversion: project.minecraft_version
}
from('docs/AGENTS.md') {
into ''
rename { 'AGENTS.md' }
}
from('docs') {
into 'META-INF/orespawn/docs'
}
Expand Down
16 changes: 0 additions & 16 deletions docs/AGENTS.md

This file was deleted.

6 changes: 6 additions & 0 deletions docs/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,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. 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
4 changes: 3 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ shaded or embeddable engine artifact.

Choose the guide that matches what you are doing:

For mod or modpack integration, start with the developer guide, then use the
API and provider references for the details.

- [Player and server guide](PLAYER_GUIDE.md)
- [Developer quick start and complete integration map](DEVELOPER_GUIDE.md)
- [Configuration field reference](CONFIGURATION.md)
Expand All @@ -18,7 +21,6 @@ Choose the guide that matches what you are doing:
- [Migration](MIGRATION.md)
- [Troubleshooting](TROUBLESHOOTING.md)
- [Versioning and release identities](VERSIONS.md)
- [Compact instructions for coding agents](AGENTS.md)

Validated examples are in `examples/`; JSON Schemas are in `schemas/`.
The provider and migration guides include OS3-compatible ranged quantities and
Expand Down
2 changes: 1 addition & 1 deletion docs/VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Examples:

| Minecraft | Loader | Target | Example full version |
| --- | --- | ---: | --- |
| 1.10.2 | Forge | `110021` | `4.1.0.110021` |
| 1.10.2 | Forge | `110021` | `4.1.1.110021` |
| 1.12.2 | Forge | `112021` | `4.0.6.112021` |
| 1.13.2 | Forge | `113021` | `4.0.6.113021` |
| 1.20.6 | Forge | `120061` | `4.0.6.120061` |
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.110021
mod_version=4.1.1.110021
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
4 changes: 2 additions & 2 deletions gradle/ide/eclipse.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ tasks.register('verifyEclipseProductionClasspath') {
}
File eclipseResources = file('bin/main')
List<File> trackedDocs = trackedDocumentationFiles()
if (trackedDocs.size() != 21) {
throw new GradleException("Expected 21 tracked documentation files, found ${trackedDocs.size()}")
if (trackedDocs.size() != 20) {
throw new GradleException("Expected 20 tracked documentation files, found ${trackedDocs.size()}")
}
trackedDocs.each { File source ->
String relative = documentationRelativePath(source)
Expand Down
15 changes: 7 additions & 8 deletions gradle/release/artifacts.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ tasks.register('verifyReleaseConfiguration') {
description = 'Validates the target-qualified release, API, schemas, reports, and publishing identity.'

doLast {
if (project.mod_version != '4.1.0.110021'
if (project.mod_version != '4.1.1.110021'
|| project.mod_group != expectedMavenGroup) {
throw new GradleException("Unexpected OreSpawn release version: ${project.mod_version}")
}
Expand Down Expand Up @@ -106,8 +106,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.110021')) {
throw new GradleException("Authoritative release location does not contain 4.1.0.110021: ${path}")
if (!file(path).getText('UTF-8').contains('4.1.1.110021')) {
throw new GradleException("Authoritative release location does not contain 4.1.1.110021: ${path}")
}
}
if (!file('docs/API.md').getText('UTF-8').contains('orespawn@[4.0.6,5.0.0)')) {
Expand Down Expand Up @@ -171,7 +171,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',
'OreSourceEditorProbeBridge',
'org/junit/', 'org/mockito/', 'net/bytebuddy/'].each { forbidden ->
if (candidateZip.entries().any { it.name.contains(forbidden) }) {
Expand All @@ -197,16 +197,15 @@ tasks.register('verifyReleaseArtifacts') {
'META-INF/orespawn/docs/VERSIONS.md',
'META-INF/orespawn/docs/schemas/orespawn-provider.schema.json',
'META-INF/orespawn/docs/schemas/orespawn-global.schema.json',
'META-INF/orespawn/docs/schemas/orespawn-world.schema.json',
'AGENTS.md'
'META-INF/orespawn/docs/schemas/orespawn-world.schema.json'
].each { required ->
if (!names.contains(required)) {
throw new GradleException("Release jar is missing ${required}")
}
}
List<File> trackedDocs = trackedDocumentationFiles()
if (trackedDocs.size() != 21) {
throw new GradleException("Expected 21 tracked documentation files, found ${trackedDocs.size()}")
if (trackedDocs.size() != 20) {
throw new GradleException("Expected 20 tracked documentation files, found ${trackedDocs.size()}")
}
trackedDocs.each { File source ->
String relative = documentationRelativePath(source)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -769,9 +769,9 @@ private static void pressDone(OreSpawnScreen screen) {
}

private static void stopIntegratedServer(Minecraft minecraft) {
// Ask the integrated server to stop while retaining the client world until
// the server and its queued play packets have drained. Clearing the world in
// this tick races Forge 1.10 packet tasks against a null client world.
// Stop the server before closing the channel. Otherwise its automatic
// disconnect can finish first and leave loadWorld waiting on a stopped thread.
if (minecraft.getIntegratedServer() != null) minecraft.getIntegratedServer().initiateShutdown();
if (minecraft.world != null) minecraft.world.sendQuittingDisconnectingPacket();
minecraft.displayGuiScreen(new GuiMainMenu());
}
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 @@ -391,7 +391,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 @@ -964,6 +964,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 @@ -1007,7 +1017,8 @@ private static void writeHumanUpgradeReport(Path destination) throws IOException
|| lower.startsWith("resource_loaded=") || lower.startsWith("os1_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 @@ -1016,12 +1027,12 @@ private static void writeHumanUpgradeReport(Path destination) throws IOException
}
}
List<String> lines = new ArrayList<>();
lines.add("OreSpawn 4.1.0.110021 Upgrade Report");
lines.add("OreSpawn 4.1.1.110021 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/cyano/orespawn/OreSpawn.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class OreSpawn {
public static OreSpawn INSTANCE;
public static final String MODID = "orespawn";
public static final String NAME = "OreSpawn";
public static final String VERSION = "4.1.0.110021";
public static final String VERSION = "4.1.1.110021";
public static final List<Path> oreSpawnConfigFiles = new ArrayList<>();
public static final List<String> additionalStoneBlocks = new ArrayList<>();
public static boolean disableVanillaOreGen;
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.110021";
public static final String VERSION = "4.1.1.110021";

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public final class DocumentationExporter {
"BIOMES.md",
"MIGRATION.md",
"TROUBLESHOOTING.md",
"AGENTS.md",
"examples/examplemod-orespawn.json",
"examples/orespawn-global.json",
"examples/orespawn-world.json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private static void writeUpgradeReport(Path worldRoot, Path configDirectory,
}

List<String> lines = new ArrayList<>();
lines.add("OreSpawn 4.1.0.110021 Upgrade Report");
lines.add("OreSpawn 4.1.1.110021 Upgrade Report");
lines.add("================================");
lines.add("");
lines.add("RESULT: Existing Mineralogy " + mineralogyVersion
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.110021 Upgrade Report" + newline
String text = "OreSpawn 4.1.1.110021 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 @@ -44,6 +45,99 @@ static void bootstrapMinecraft() {
Forge12TestBootstrap.registerVanilla();
}

@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 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 translatesOs1MetadataFractionalFrequencyExclusiveHeightAndPlusDimensions() throws Exception {
JsonObject source = new JsonParser().parse("{\"dimensions\":["
Expand Down
Loading
Loading