Phase 9 begins: bigger, sparser veins, a mine-through respawn block, left-out lines

Phase 8 approved (2026-11-09). Adrian's Phase 9 answers: left-out Pokemon rare
in fitting zones; legendaries from crafted summons; no public release.

- Ore veins more sporadic but bigger: nodes about 40 % rarer, veins about 30 %
  further apart, each one block larger in radius. 1.5-3x the ore overall; a
  new island is needed to see it. World check on the regenerated island passes.
- The respawn block (Regenerating Ore Veins' regenerator): the aim passes
  through it unless sneaking (mixin, the pack's first), so ore behind it can be
  mined; much fainter glass through KubeJS assets. Self-test
  regenerator_lets_the_aim_through casts a real ray.
- 31 lines (67 species) with no matching island biome, or no spawn data
  (Rotom), get rare homes in fitting zones (world/zones.json -> homeless).
  Existing spawns and guardians don't change. JEI data and quests regenerated.
- surface_nodes_lie_in_the_ground checks the node's centre column: a wider
  node's edge can lie under a tree or a slope.
- Roadmap: every implemented Pokemon obtainable; Iris and Complementary
  Reimagined as the default shader.

Self-tests and the island check pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
claudeandClaude Opus 5.5 committed 2026-11-09 12:45:44 +01:00
1 parent 0be2c2e5c6
commit e206664b3d
45 files changed
+2723 -242

No files matched your search

@@ -0,0 +1,25 @@
package dev.cobblesurvival.mixin;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* A mined vein block waiting to grow back (Regenerating Ore Veins' regenerator) no longer stops the player's aim, so the
* ore behind it can be mined (Adrian, 2026-11-09). It keeps its outline while sneaking: that's how its info is opened.
* Named by string, so the companion mod needs the vein mod only at run time.
*/
@Mixin(targets = "net.stargazer.regenerating_ore_veins.RegeneratorBlock", remap = false)
abstract class RegeneratorBlockMixin {
@Inject(method = "getShape", at = @At("HEAD"), cancellable = true)
private void cobblesurvival$aimThrough(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context, CallbackInfoReturnable<VoxelShape> result) {
if (!context.isDescending()) result.setReturnValue(Shapes.empty());
}
}
@@ -7,6 +7,7 @@ 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
@@ -44,8 +45,9 @@ object OreNodeTests {
if (cave) {
s.check(level.getBiome(ground.above()).`is`(node.biome!!)) { "the ${node.vein} at ${ground.toShortString()} isn't in ${node.biome}" }
} else {
val top = blocks.maxBy { it.y }
s.check(level.canSeeSky(top.above())) { "the ${node.vein} at ${ground.toShortString()} is under cover" }
// 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" }
}
}
@@ -7,6 +7,7 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.level.ClipContext
import net.minecraft.world.level.GameType
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.phys.Vec3
@@ -26,11 +27,35 @@ object VeinTests {
private val REGENERATOR = ResourceLocation.fromNamespaceAndPath("regenerating_ore_veins", "regenerator_block")
fun all() = listOf(
SelfTestCase("regenerator_lets_the_aim_through", 20, ::aimThrough),
SelfTestCase("vein_regrows_after_unload", 1200, ::afterUnload),
SelfTestCase("vein_mined_before_restart", 400, ::beforeRestart),
SelfTestCase("vein_regrows_after_restart", 400, ::afterRestart, afterRestart = true),
)
/**
* A mined vein block waiting to grow back doesn't stop the player's aim, so the ore behind it can be mined (Adrian,
* 2026-11-09; mixin/RegeneratorBlockMixin.java); while sneaking the player can target it, which opens its info.
*/
private fun aimThrough(s: Scenario) {
val regenerator = BuiltInRegistries.BLOCK.get(ResourceLocation.parse("regenerating_ore_veins:regenerator_block"))
s.check(regenerator != Blocks.AIR) { "Regenerating Ore Veins' regenerator isn't installed" }
val player = s.player()
val pos = s.helper.absolutePos(BlockPos(7, 2, 7))
val behind = pos.east()
s.level.setBlockAndUpdate(pos, regenerator.defaultBlockState())
s.level.setBlockAndUpdate(behind, Blocks.STONE.defaultBlockState())
fun aimedAt(): BlockPos {
val from = Vec3(pos.x - 2.5, pos.y + 0.5, pos.z + 0.5)
return s.level.clip(ClipContext(from, from.add(6.0, 0.0, 0.0), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).blockPos
}
s.check(aimedAt() == behind) { "the aim stops at ${aimedAt().toShortString()}, not at the block behind the regenerator" }
player.isShiftKeyDown = true
s.check(aimedAt() == pos) { "sneaking, the aim doesn't find the regenerator (it stops at ${aimedAt().toShortString()})" }
player.isShiftKeyDown = false
s.helper.succeed()
}
private fun afterUnload(s: Scenario) {
val level = s.level
val pos = spot(level, UNLOAD_OFFSET)
@@ -12,6 +12,9 @@ Mechanics for the Cobblemon Survival Pack that no existing addon covers.
Not affiliated with Cobblemon, The Pokémon Company, Nintendo, Game Freak or Creatures Inc.
'''
[[mixins]]
config = "cobblesurvival.mixins.json"
[[dependencies.${mod_id}]]
modId = "minecraft"
type = "required"
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,8 @@
{
"required": true,
"minVersion": "0.8",
"package": "dev.cobblesurvival.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": ["RegeneratorBlockMixin"],
"injectors": {"defaultRequire": 1}
}