package dev.cobblesurvival.selftest import dev.cobblesurvival.dev.OreVeins import dev.cobblesurvival.ore.OreNodes import dev.cobblesurvival.zone.Zones import net.minecraft.core.BlockPos import net.minecraft.core.Direction import net.minecraft.gametest.framework.GameTestAssertException import net.minecraft.world.level.ChunkPos import net.minecraft.world.level.levelgen.Heightmap /** * Ore nodes on the island (Adrian, 2026-10-30): a surface node is a small lump of ore in the ground of its zone with * open air above it; a cave node lies on the floor of its cave biome, touching the cave's air, not buried in a wall. * Each test places one node on purpose near its zone's sample point and checks it as Regenerating Ore Veins tracks it. */ object OreNodeTests { fun all() = listOf( SelfTestCase("surface_nodes_lie_in_the_ground", 20, { s -> nodeTest(s, "button_isle", cave = false) }, islandOnly = true), SelfTestCase("cave_nodes_lie_on_the_cave_floor", 20, { s -> nodeTest(s, "deep_dark", cave = true) }, islandOnly = true), ) private fun nodeTest(s: Scenario, zone: String, cave: Boolean) { val level = s.level val node = OreNodes.nodes.firstOrNull { it.zone == zone && it.cave == cave } ?: throw GameTestAssertException("no ${if (cave) "cave" else "surface"} node kind in $zone") val sample = Zones.samples[zone] ?: throw GameTestAssertException("no sample point for $zone") val home = ChunkPos(BlockPos(sample.x, 0, sample.z)) // Next to the sample chunk first (the guardian stands on the sample point), then around it. val chunks = listOf(ChunkPos(home.x + 2, home.z)) + (-1..1).flatMap { dx -> (-1..1).map { dz -> ChunkPos(home.x + dx, home.z + dz) } } val grounds = chunks.asSequence() .onEach { level.getChunk(it.x, it.z) } .map { OreNodes.fill(level, it, only = node, force = true) } .firstOrNull { it.isNotEmpty() } ?: throw GameTestAssertException("no spot for a ${node.vein} near $zone's sample point") for (ground in grounds) { val blocks = BlockPos.betweenClosed(ground.offset(-node.radius - 1, -node.radius - 1, -node.radius - 1), ground.offset(node.radius + 1, node.radius + 1, node.radius + 1)) .map { it.immutable() } .filter { OreVeins.veinAt(level, it) == node.vein } s.check(blocks.isNotEmpty()) { "the ${node.vein} at ${ground.toShortString()} isn't tracked by Regenerating Ore Veins" } val exposed = blocks.any { block -> Direction.entries.any { level.getBlockState(block.relative(it)).isAir } } s.check(exposed) { "the ${node.vein} at ${ground.toShortString()} touches no air: it's buried" } if (cave) { s.check(level.getBiome(ground.above()).`is`(node.biome!!)) { "the ${node.vein} at ${ground.toShortString()} isn't in ${node.biome}" } } else { // Open ground over the node's centre (leaves don't count): a wide node's edge may lie under a tree or a slope. val surface = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, ground.x, ground.z) s.check(surface <= ground.y + 2) { "the ${node.vein} at ${ground.toShortString()} is under cover (ground at $surface)" } s.check(blocks.all { Zones.at(level, it)?.id == zone }) { "the ${node.vein} at ${ground.toShortString()} reaches out of $zone" } } } s.helper.succeed() } }