Phase 5: field moves from Cobblemon HMs
Adrian (2026-10-31): use Cobblemon HMs; mining ore is the one hard requirement, furnaces get lit by a Pokemon inside a Phase 6 machine. - Cobblemon HMs 4.1.0 in the pack (Modrinth), default config. - Self-test rock_smash_mines_veins: HMs' Rock Smash breaks a regenerating vein, the ore drops and the vein becomes a regenerator. - HMs' Trainer Ditto (a wild Ditto underneath) is exempt from the hostility scan and the stray despawn (world/SpecialPokemon.kt). - Docs: licenses, addon status, design, balance, roadmap note, Phase 5 checklist with the open questions for Adrian. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea21bb725a
commit
56ffdd9f2e
14 files changed
+145
-6
No files matched your search
@@ -0,0 +1,62 @@
|
||||
package dev.cobblesurvival.selftest
|
||||
|
||||
import dev.cobblesurvival.dev.OreVeins
|
||||
import net.minecraft.commands.arguments.EntityAnchorArgument
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.GameType
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Phase 5 field moves come from Cobblemon HMs (Adrian, 2026-10-31); mining ore is the one hard requirement. Rock Smash
|
||||
* must mine a regenerating vein the normal way: the ore drops and Regenerating Ore Veins turns the block into a
|
||||
* regenerator, so the vein grows back. The test fires HMs' own Rock Smash handler (by reflection) at a one-block
|
||||
* coal vein, away from spawn, since HMs respects spawn protection.
|
||||
*/
|
||||
object FieldMoveTests {
|
||||
private const val VEIN = "selftest"
|
||||
private const val OFFSET = 64
|
||||
private val REGENERATOR = ResourceLocation.parse("regenerating_ore_veins:regenerator_block")
|
||||
|
||||
fun all() = listOf(SelfTestCase("rock_smash_mines_veins", 100, ::rockSmashMinesVeins))
|
||||
|
||||
private fun rockSmashMinesVeins(s: Scenario) {
|
||||
val level = s.level
|
||||
val pos = level.sharedSpawnPos.let { BlockPos(it.x + OFFSET, SelfTest.PLATFORM_Y, it.z) }
|
||||
val player = s.player()
|
||||
val start = player.position()
|
||||
s.helper.startSequence()
|
||||
.thenExecute {
|
||||
s.moveTo(player, pos.x + 0.5, pos.y - 1.0, pos.z + 3.5) // forces the chunks around the vein
|
||||
s.check(OreVeins.place(level, pos, VEIN, RandomSource.create(1L)) > 0) { "the test vein was not placed" }
|
||||
s.check(level.getBlockState(pos).`is`(Blocks.COAL_ORE)) { "the test vein is ${level.getBlockState(pos)}" }
|
||||
player.lookAt(EntityAnchorArgument.Anchor.EYES, Vec3.atCenterOf(pos))
|
||||
s.check(rockSmash(player)) { "Rock Smash refused to break the ore" }
|
||||
player.teleportTo(start.x, start.y, start.z)
|
||||
}
|
||||
.thenWaitUntil {
|
||||
val block = BuiltInRegistries.BLOCK.getKey(level.getBlockState(pos).block)
|
||||
s.check(block == REGENERATOR) { "the mined vein block is $block, not a regenerator: it won't grow back" }
|
||||
val drops = level.getEntitiesOfClass(ItemEntity::class.java, AABB(pos).inflate(4.0)) { it.item.`is`(Items.COAL) }
|
||||
s.check(drops.isNotEmpty()) { "Rock Smash dropped no coal" }
|
||||
}
|
||||
.thenExecute {
|
||||
level.getEntitiesOfClass(ItemEntity::class.java, AABB(pos).inflate(4.0)).forEach { it.discard() }
|
||||
player.setGameMode(GameType.CREATIVE) // breaking a regenerator in creative removes the vein for good
|
||||
player.gameMode.destroyBlock(pos)
|
||||
}
|
||||
.thenSucceed()
|
||||
}
|
||||
|
||||
private fun rockSmash(player: ServerPlayer): Boolean {
|
||||
val handler = Class.forName("com.shier.cobblemonhms.ability.handlers.RockSmashHandler")
|
||||
return handler.getMethod("execute", ServerPlayer::class.java).invoke(handler.getField("INSTANCE").get(null), player) as Boolean
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ object SelfTest {
|
||||
private val cases: List<SelfTestCase> get() =
|
||||
PermadeathTests.all() + SurvivalRulesTests.all() + ZoneTests.all() + HazardTests.all() + GuardianTests.all() +
|
||||
VeinTests.all() + OreNodeTests.all() + DropTests.all() + ProgressionTests.all() +
|
||||
CatchingTests.all() + WorldRulesTests.all()
|
||||
CatchingTests.all() + WorldRulesTests.all() + FieldMoveTests.all()
|
||||
|
||||
private var running: List<Scenario> = emptyList()
|
||||
private var forced: List<ChunkPos> = emptyList()
|
||||
|
||||
Reference in new issue
Block a user