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
84 changes: 77 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,67 @@ concurrency:
cancel-in-progress: true

jobs:
cold-forge-bootstrap:
name: Cold Forge bootstrap
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Install pinned Java 25 ForgeGradle Mavenizer runtime
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '25.0.3+9.0.LTS'

- name: Install pinned Java 8 compilation toolchain
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '8.0.502+7'

- name: Install pinned Java 17 Gradle runtime
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '17.0.1+12'

- name: Bootstrap Forge from an empty cache
shell: bash
env:
GRADLE_USER_HOME: ${{ runner.temp }}/orespawn-cold-gradle
run: |
set -euo pipefail
test ! -e .gradle
test ! -e "$GRADLE_USER_HOME"
mkdir -p "$GRADLE_USER_HOME"
chmod +x ./gradlew
gradle_args=(
classes verifyLegacyFixtures
--no-daemon --no-build-cache --stacktrace --max-workers=2
-Dorg.gradle.java.installations.paths="$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64"
-Dorg.gradle.java.installations.auto-detect=false
-Dorg.gradle.java.installations.auto-download=false
)
./gradlew "${gradle_args[@]}"

- name: Verify same-cache bootstrap offline
shell: bash
env:
GRADLE_USER_HOME: ${{ runner.temp }}/orespawn-cold-gradle
run: |
set -euo pipefail
gradle_args=(
classes verifyLegacyFixtures
--rerun-tasks --offline --no-daemon --no-build-cache --stacktrace --max-workers=2
-Dorg.gradle.java.installations.paths="$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64"
-Dorg.gradle.java.installations.auto-detect=false
-Dorg.gradle.java.installations.auto-download=false
)
./gradlew "${gradle_args[@]}"

build:
name: Build, test, and audit
runs-on: ubuntu-latest
Expand All @@ -26,17 +87,23 @@ jobs:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Install Java 8 toolchain
- name: Install pinned Java 25 ForgeGradle Mavenizer runtime
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '25.0.3+9.0.LTS'

- name: Install pinned Java 8 compilation toolchain
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '8.0.502+7'

- name: Install Java 17 for Gradle
- name: Install pinned Java 17 Gradle runtime
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: microsoft
java-version: '17'
distribution: temurin
java-version: '17.0.1+12'

- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6
Expand All @@ -48,6 +115,9 @@ jobs:
run: >-
./gradlew clean check build javadoc verifyReleaseArtifacts writeReleaseChecksums
verifyEclipseProductionClasspath --no-daemon --stacktrace
-Dorg.gradle.java.installations.paths="$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64"
-Dorg.gradle.java.installations.auto-detect=false
-Dorg.gradle.java.installations.auto-download=false

- name: Upload audited release candidate
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
Expand All @@ -56,9 +126,9 @@ jobs:
if-no-files-found: error
retention-days: 30
path: |
build/libs/OreSpawn-4.0.8.113021.jar
build/libs/OreSpawn-4.0.8.113021-sources.jar
build/libs/OreSpawn-4.0.8.113021-javadoc.jar
build/libs/OreSpawn-4.0.16.113021.jar
build/libs/OreSpawn-4.0.16.113021-sources.jar
build/libs/OreSpawn-4.0.16.113021-javadoc.jar
build/release/SHA256SUMS
CHANGELOG.txt

Expand Down
23 changes: 18 additions & 5 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,23 @@ jobs:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Install Java 8 toolchain
- name: Install pinned Java 25 ForgeGradle Mavenizer runtime
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '25.0.3+9.0.LTS'

- name: Install pinned Java 8 compilation toolchain
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '8.0.502+7'

- name: Install Java 17 for Gradle
- name: Install pinned Java 17 Gradle runtime
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: microsoft
java-version: '17'
distribution: temurin
java-version: '17.0.1+12'

- name: Set up Gradle
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6
Expand All @@ -49,7 +55,14 @@ jobs:
- name: Compile production code
run: |
chmod +x ./gradlew
./gradlew clean classes --no-daemon --stacktrace
gradle_args=(
clean classes
--no-daemon --stacktrace --max-workers=2
-Dorg.gradle.java.installations.paths="$JAVA_HOME,$JAVA_HOME_8_X64,$JAVA_HOME_25_X64"
-Dorg.gradle.java.installations.auto-detect=false
-Dorg.gradle.java.installations.auto-download=false
)
./gradlew "${gradle_args[@]}"

- name: Analyze
uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4
44 changes: 44 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
Version 4.0.16.113021

* Adopt the shared 4.0.16 release identity. Forge 1.13 has neither
three-dimensional biome-cell attribution nor a server-side GameTest harness,
so the 4.0.15 attribution and 4.0.16 GameTest lifecycle repairs are not
applicable on this target.
* Ordinary dedicated benchmark servers continue to stop automatically when
requested.

Version 4.0.14.113021

* Convert exposed one-layer vanilla Snow from the first free cell immediately
above Minecraft's motion-blocking surface when a dimension supplies a custom
snow material.
* Retain the existing surface Ice conversion and leave buried or authored Snow
and Ice unchanged.

Version 4.0.13.113021

* Give the public ore-dimension builder the exact biome include/exclude and
biome-dictionary filter support already available in provider JSON.
* Accept valid namespaced geome IDs in both creation-editor validation paths
while preserving legacy unnamespaced geome keys.
* API major 1, schemas, existing profiles, generated chunks, and worldgen
behaviour are unchanged.

Version 4.0.10.113021

* Evaluate Stable Layers rock min_y and max_y bounds against actual world Y
instead of the vertically shifted formation coordinate.
* Preserve the shifted formation identity for layer, family, and rock choice
while preventing vanilla Stone fallback near dimension floors and ceilings.
* Apply the correction only while generating new chunks; existing chunks and
saved profiles remain unchanged.

Version 4.0.9.113021

* Replace provider-declared natural terrain hosts during the existing geology
scan before structure and vegetation features can author matching blocks.
* Keep air, fluids, bedrock, and block entities protected even when their block
IDs are mistakenly declared as terrain hosts.
* Apply the correction only while generating new chunks; existing chunks and
saved profiles remain unchanged.

Version 4.0.8.113021

* Preserve long host, tag, and biome-list values when OreSpawn editors load
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ End" policy used by mods such as Base Metals.
This is not the unrelated mod that adds mobs and dimensions under the same
name.

This branch builds target-qualified version `4.0.8.113021`: the OreSpawn 4.0.8
This branch builds target-qualified version `4.0.16.113021`: the OreSpawn 4.0.16
feature set for Minecraft 1.13.2 and Forge. See the
[versioning policy](docs/VERSIONS.md) for the encoding and release convention.

Expand Down Expand Up @@ -95,9 +95,11 @@ exported to `config/orespawn-guide/` without overwriting existing files.

## Building

Run Gradle with Java 17 from the repository root. Install the exact Temurin
`8.0.502+7` toolchain used to compile production code and test fixtures for
Minecraft 1.13.2; the build rejects a different Java 8 toolchain:
Run Gradle with Java 17 from the repository root. Install exact Temurin
`25.0.3+9` for ForgeGradle's Mavenizer and exact Temurin `8.0.502+7` for the
Minecraft 1.13.2 compilation and fixture toolchain. Java 17 remains the Gradle
runtime, while production bytecode remains Java 8; the build rejects a
different Java 8 toolchain:

```powershell
.\gradlew.bat clean check build javadoc verifyReleaseArtifacts writeReleaseChecksums --no-daemon
Expand Down
49 changes: 40 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import groovy.json.JsonSlurper
import groovy.xml.XmlSlurper
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import java.util.jar.Manifest
Expand Down Expand Up @@ -35,6 +36,9 @@ if (versionParts[3] != expectedTargetVersion) {
ext.functional_version = versionParts[0..2].join('.')
ext.display_version = project.mod_version
ext.release_tag = project.mod_version
def expectedMavenGroup = 'zone.moddev.mc.orespawn'
def expectedMavenArtifact = 'OreSpawn'
def expectedMavenCoordinate = "${expectedMavenGroup}:${expectedMavenArtifact}:${project.version}"

java {
toolchain {
Expand Down Expand Up @@ -462,6 +466,7 @@ level-name=surface-integration-world
level-seed=zsjpxah
level-type=default
online-mode=false
server-port=0
allow-nether=true
generate-structures=false
spawn-protection=0
Expand Down Expand Up @@ -671,7 +676,7 @@ tasks.named('jar', Jar) {
'Implementation-Vendor' : 'SkyBlade1978',
'OreSpawn-API-Version' : '1',
'FMLAT' : 'accesstransformer.cfg',
'Maven-Artifact' : "${project.group}:${base.archivesName.get()}:${project.version}",
'Maven-Artifact' : expectedMavenCoordinate,
'Built-On-Java' : '8',
'Built-On' : "${project.minecraft_version}-${project.forge_version}"
])
Expand Down Expand Up @@ -727,7 +732,8 @@ def preparedReleaseDir = providers.gradleProperty('preparedReleaseDir')
tasks.register('verifyReleaseConfiguration') {
group = 'verification'
doLast {
if (project.mod_version != '4.0.8.113021'
if (project.mod_version != '4.0.16.113021'
|| project.mod_group != expectedMavenGroup
|| project.minecraft_version != '1.13.2'
|| project.forge_version != '25.0.223'
|| project.mapping_channel != 'snapshot'
Expand All @@ -740,11 +746,11 @@ tasks.register('verifyReleaseConfiguration') {
throw new GradleException('Unexpected dispatcher or Java target metadata')
}
List<String> expectedPublicArtifacts = [
'OreSpawn-4.0.8.113021.jar',
'OreSpawn-4.0.8.113021-sources.jar',
'OreSpawn-4.0.8.113021-javadoc.jar'
'OreSpawn-4.0.16.113021.jar',
'OreSpawn-4.0.16.113021-sources.jar',
'OreSpawn-4.0.16.113021-javadoc.jar'
]
if (base.archivesName.get() != 'OreSpawn'
if (base.archivesName.get() != expectedMavenArtifact
|| expectedReleaseFiles.get().collect { it.toString() } != expectedPublicArtifacts) {
throw new GradleException('Public artifacts must use the version-only OreSpawn filename contract')
}
Expand All @@ -759,7 +765,7 @@ tasks.register('verifyReleaseConfiguration') {
'src/main/java/zone/moddev/mc/orespawn/worldgen/LegacyMineralogyProfileMigration.java',
'README.md', 'CHANGELOG.txt'
].each { path ->
if (!file(path).getText('UTF-8').contains('4.0.8.113021')) {
if (!file(path).getText('UTF-8').contains('4.0.16.113021')) {
throw new GradleException("Release identity missing from ${path}")
}
}
Expand Down Expand Up @@ -871,6 +877,7 @@ tasks.register('verifyReleaseArtifacts') {
|| manifest.getValue('Implementation-Version') != project.mod_version
|| manifest.getValue('OreSpawn-API-Version') != '1'
|| manifest.getValue('FMLAT') != 'accesstransformer.cfg'
|| manifest.getValue('Maven-Artifact') != expectedMavenCoordinate
|| manifest.getValue('Implementation-Timestamp') != null) {
throw new GradleException('Release manifest is incorrect or volatile')
}
Expand Down Expand Up @@ -969,8 +976,8 @@ def mavenUploadPassword = providers.environmentVariable('MAVEN_UPLOAD_PASSWORD')
publishing {
publications {
mavenJava(MavenPublication) {
groupId = project.group.toString()
artifactId = base.archivesName.get()
groupId = expectedMavenGroup
artifactId = expectedMavenArtifact
version = project.version.toString()
if (preparedReleaseDir.isPresent()) {
File prepared = file(preparedReleaseDir.get())
Expand Down Expand Up @@ -1006,6 +1013,26 @@ publishing {
}
}
}
tasks.register('verifyMavenCoordinates') {
group = 'verification'
description = 'Verifies the generated POM uses OreSpawn\'s mod-specific Maven namespace.'
dependsOn tasks.named('generatePomFileForMavenJavaPublication')
doLast {
File pomFile = layout.buildDirectory.file(
'publications/mavenJava/pom-default.xml').get().asFile
if (!pomFile.isFile()) {
throw new GradleException("Generated Maven POM does not exist: ${pomFile}")
}
def pom = new XmlSlurper(false, false).parse(pomFile)
def actual = [pom.groupId.text(), pom.artifactId.text(), pom.version.text()]
def expected = [expectedMavenGroup, expectedMavenArtifact,
project.version.toString()]
if (project.group.toString() != expectedMavenGroup || actual != expected) {
throw new GradleException("Expected Maven coordinate ${expected.join(':')}, " +
"found ${actual.join(':')}")
}
}
}
tasks.register('validateMavenReleaseCredentials') {
group = 'publishing'
doLast {
Expand All @@ -1021,11 +1048,14 @@ tasks.register('validateMavenReleaseCredentials') {
}
tasks.withType(PublishToMavenRepository).configureEach {
dependsOn tasks.named('validateMavenReleaseCredentials')
dependsOn tasks.named('verifyMavenCoordinates')
dependsOn preparedReleaseDir.isPresent()
? tasks.named('verifyPreparedReleaseArtifacts')
: tasks.named('verifyReleaseArtifacts')
}

tasks.named('check') { dependsOn tasks.named('verifyMavenCoordinates') }

eclipse {
classpath {
downloadSources = true
Expand Down Expand Up @@ -1184,6 +1214,7 @@ level-name=surface-integration-world
level-seed=zsjpxah
level-type=default
online-mode=false
server-port=0
allow-nether=true
generate-structures=false
spawn-protection=0
Expand Down
7 changes: 7 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ WorldgenProvider provider = WorldgenProvider.builder("examplemod", 1)
`OilDefinition` and template `.oil(...)` remain deprecated migration adapters
for one legacy oil rule. New integrations should use `FluidDepositDefinition`.

Ore dimension builders expose the same biome filters as provider JSON and
fluid-deposit builders. Use `.biome(...)` and `.biomeDictionary(...)` for
inclusions, with `.excludeBiome(...)` and `.excludeBiomeDictionary(...)` for
exclusions. These methods work on both explicit `.dimension(...)` rules and
`.dimensionSelector(...)` fallbacks; built definitions and their returned
filter sets are immutable.

Create one `BiomeRegistrar` during normal mod construction. It attaches to the
calling mod's event bus and defers biome factories until Forge's biome registry
event. `OreSpawnBiomes.copyAndRegister` clones a known biome without adding a
Expand Down
7 changes: 7 additions & 0 deletions docs/BIOMES.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ lets OreSpawn replace the actual exposed ground while preserving later trees,
plants, authored structures, and block entities. In ceiling dimensions,
`ceiling_block` applies to the roof underside and does not replace the roof top.

Provider-declared `terrain_dimensions.host_blocks` are resolved by one terrain
scan at the start of `LOCAL_MODIFICATIONS`, immediately before provider
surfaces. Matching natural blocks already present in base terrain are eligible
for geology; matching blocks authored by later structure or vegetation stages
are not. Air, fluids, bedrock, and block-entity states remain protected even if
a provider mistakenly lists their block IDs as terrain hosts.

Surface correction is generation-only. Installing or updating OreSpawn does
not rewrite already generated chunks; travel into new terrain to see a changed
provider surface definition.
Expand Down
Loading
Loading