Phase 4: veins in every chunk, drops for the mobs the island lacks

Ore veins: make_world.py loads the island again row by row until
Regenerating Ore Veins has filled every chunk (/cobblesurvival veins
unfilled), cave tiers sit at their biome's depths, small zones get denser
veins, showcase veins are full size. The world report checks surface
tiers against the zone grid, cave tiers within two biome cells of their
cave, and fails on unfilled chunks; the template passes (37,689 chunks).

Drops: tools/drop_audit.py checks every creature drop a recipe or brewing
needs (docs/pokemon-drops.md). Blaze rods, ghast tears, breeze rods,
shulker shells and nether stars now drop from Pokemon through species
additions (self-test drop_additions_apply). The field guide counts vanilla
mobs as absent, applies species additions and reads the veins as sources.

Cobblebase tried (loads, self-tests pass) and left out until Adrian
decides its scope. Phase 4 checklist with the open questions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
claudeandClaude Opus 5.5 committed 2026-10-30 03:36:50 +01:00
1 parent 5d275e4e14
commit 1a1fb93da8
33 files changed
+1279 -126

No files matched your search

@@ -0,0 +1,34 @@
package dev.cobblesurvival.selftest
import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.google.gson.JsonParser
import dev.cobblesurvival.CobbleSurvival
import net.minecraft.gametest.framework.GameTestAssertException
import net.minecraft.resources.ResourceLocation
/**
* Roadmap Phase 4, unique drops: the core data pack gives some Pokémon the drops of mobs the island doesn't have
* (blaze rods, ghast tears, ...) through Cobblemon's species additions (`species_additions/`). This checks that
* Cobblemon really applied every item they add, as tools/drop_audit.py assumes.
*/
object DropTests {
fun all() = listOf(SelfTestCase("drop_additions_apply", 20, ::dropAdditionsApply))
private fun dropAdditionsApply(s: Scenario) {
val additions = s.level.server.resourceManager.listResources("species_additions") { it.path.endsWith(".json") }
.filterKeys { it.namespace == CobbleSurvival.MOD_ID }
s.check(additions.isNotEmpty()) { "the core data pack has no species additions" }
for ((id, resource) in additions) {
val json = resource.openAsReader().use { JsonParser.parseReader(it).asJsonObject }
val target = ResourceLocation.parse(json.get("target").asString)
val species = PokemonSpecies.getByIdentifier(target) ?: throw GameTestAssertException("$id: no species $target")
val drops = species.drops.entries.filterIsInstance<ItemDropEntry>().map { it.item }.toSet()
for (entry in json.getAsJsonObject("drops")?.getAsJsonArray("entries") ?: continue) {
val item = ResourceLocation.parse(entry.asJsonObject.get("item").asString)
s.check(item in drops) { "${species.name} doesn't drop $item, although $id adds it" }
}
}
s.helper.succeed()
}
}
@@ -51,7 +51,7 @@ object SelfTest {
private val cases: List<SelfTestCase> get() =
PermadeathTests.all() + SurvivalRulesTests.all() + ZoneTests.all() + HazardTests.all() + GuardianTests.all() +
VeinTests.all()
VeinTests.all() + DropTests.all()
private var running: List<Scenario> = emptyList()
private var forced: List<ChunkPos> = emptyList()
@@ -1,5 +1,6 @@
package dev.cobblesurvival.selftest
import dev.cobblesurvival.dev.OreVeins
import net.minecraft.core.BlockPos
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
@@ -114,9 +115,5 @@ object VeinTests {
BuiltInRegistries.BLOCK.getKey(level.getBlockState(pos).block) == REGENERATOR
/** Moves the vein block's "last mined" time far into the past; the mod keeps it in its saved data. */
private fun rewind(level: ServerLevel, pos: BlockPos) {
val data = Class.forName("net.stargazer.regenerating_ore_veins.VeinSavedData")
val saved = data.getMethod("get", ServerLevel::class.java).invoke(null, level)
data.getMethod("markMined", BlockPos::class.java, Long::class.javaPrimitiveType).invoke(saved, pos, 1L)
}
private fun rewind(level: ServerLevel, pos: BlockPos) = OreVeins.markMined(level, pos, 1L)
}