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:
claudeandClaude Opus 5.5 committed 2026-10-31 03:00:07 +01:00
1 parent ea21bb725a
commit 56ffdd9f2e
14 files changed
+145 -6

No files matched your search

+1
View File
@@ -40,6 +40,7 @@ Checked 2026-10-28 against Cobblemon **1.8.4** (NeoForge, MC 1.21.1). Re-check b
| Cobblemon Fight or Flight Reborn | wild Pokémon flee or fight back (Phase 2) | `fightorflight-neoforge-0.11.1.jar` (MR `OD7X9rYz`, CF `9156010`) | MR + CF | ✅ Declares `[1.8.2,)` | | Cobblemon Fight or Flight Reborn | wild Pokémon flee or fight back (Phase 2) | `fightorflight-neoforge-0.11.1.jar` (MR `OD7X9rYz`, CF `9156010`) | MR + CF | ✅ Declares `[1.8.2,)` |
| Cobblemon TP-Pastures | pastured Pokémon teleported back, not recalled (Phase 2) | `cobblemon_tp_pastures-1.21.1-1.3.0.jar` (MR `so0hyqC2`) | MR + CF | ⚠️ Declares `[1.7.1,)`; loads on 1.8.4, behaviour still to be checked in-game | | Cobblemon TP-Pastures | pastured Pokémon teleported back, not recalled (Phase 2) | `cobblemon_tp_pastures-1.21.1-1.3.0.jar` (MR `so0hyqC2`) | MR + CF | ⚠️ Declares `[1.7.1,)`; loads on 1.8.4, behaviour still to be checked in-game |
| Lootr | loot containers refill 1 hour after first opened, loot per player (Phase 2) | `lootr-neoforge-1.21.1-1.11.38.127.jar` (MR `SPOrIzX8`, CF `8968561`) | MR + CF | n/a (no Cobblemon dependency); converts Cobblemon's loot chests too | | Lootr | loot containers refill 1 hour after first opened, loot per player (Phase 2) | `lootr-neoforge-1.21.1-1.11.38.127.jar` (MR `SPOrIzX8`, CF `8968561`) | MR + CF | n/a (no Cobblemon dependency); converts Cobblemon's loot chests too |
| Cobblemon HMs | field moves (Phase 5) | `cobblemon-hms-neoforge-4.1.0.jar` (MR `uC02CqRy`) | MR (CF link not resolved yet) | ✅ Declares Cobblemon ≥ 1.8.0; loads and runs on 1.8.4 (self-tests, incl. Rock Smash on a regenerating vein). Added 2026-10-31 |
| Better Advanced Tooltips | none: ships *inside* KubeJS as jar-in-jar | — | — | Modrinth marks it as a required KubeJS dependency, but KubeJS declares it optional and embeds it. Not referenced separately | | Better Advanced Tooltips | none: ships *inside* KubeJS as jar-in-jar | — | — | Modrinth marks it as a required KubeJS dependency, but KubeJS declares it optional and embeds it. Not referenced separately |
JEI declares Minecraft `[1.21, 1.21.1)` in every 1.21.1 build, which a strict reading excludes; NeoForge 21.1.265 loads it anyway (server boot checked 2026-10-28). JEI declares Minecraft `[1.21, 1.21.1)` in every 1.21.1 build, which a strict reading excludes; NeoForge 21.1.265 loads it anyway (server boot checked 2026-10-28).
+1
View File
@@ -27,6 +27,7 @@ Every tunable lives in a config file or in this table. **Placeholder** means gue
| Guardian strength | strongest Pokémon spawning in the zone, band top + 5 levels, 1.5× size, uncatchable | Decided (Adrian, 2026-10-30) | `tools/zone_spawns.py` (`GUARDIAN_*`), `world/zones.json` → `guardian.species` | | | Guardian strength | strongest Pokémon spawning in the zone, band top + 5 levels, 1.5× size, uncatchable | Decided (Adrian, 2026-10-30) | `tools/zone_spawns.py` (`GUARDIAN_*`), `world/zones.json` → `guardian.species` | |
| Guardian drops | Button Isle 10 Poké Balls + 4 Potions; Southwold 6 Great Balls + 4 Exp. Candy S; Westmarch and Jungle Mire Waders + 4 Pecha Berries + 2 Exp. Candy M; Mire and Highlands 3 Icy Rocks + 4 Super Potions; Sunscorch 3 Heat Rocks + 2 Exp. Candy L; Frostpeak and Deep Dark 3 Icy Rocks + 2 Exp. Candy L; Deep Sea Mystic Water + 3 Exp. Candy M | Decided (Adrian, 2026-10-30) | `world/zones.json` → `guardian.drops` | 3 rocks make one full fur or hide set | | Guardian drops | Button Isle 10 Poké Balls + 4 Potions; Southwold 6 Great Balls + 4 Exp. Candy S; Westmarch and Jungle Mire Waders + 4 Pecha Berries + 2 Exp. Candy M; Mire and Highlands 3 Icy Rocks + 4 Super Potions; Sunscorch 3 Heat Rocks + 2 Exp. Candy L; Frostpeak and Deep Dark 3 Icy Rocks + 2 Exp. Candy L; Deep Sea Mystic Water + 3 Exp. Candy M | Decided (Adrian, 2026-10-30) | `world/zones.json` → `guardian.drops` | 3 rocks make one full fur or hide set |
| Mire poison | Poison I for 7 s, renewed every 5 s while in the Mire without Mire Waders | Decided (Adrian, 2026-10-30) | `datapacks/core/data/cobblesurvival/zone_hazards/mire.json` | Vanilla Poison stops at half a heart | | Mire poison | Poison I for 7 s, renewed every 5 s while in the Mire without Mire Waders | Decided (Adrian, 2026-10-30) | `datapacks/core/data/cobblesurvival/zone_hazards/mire.json` | Vanilla Poison stops at half a heart |
| Field moves (Cobblemon HMs) | mod defaults: all 39 abilities on, no level minimum, no fullness or friendship cost; Rock Smash breaks up to 32 connected ore blocks with no cooldown | Placeholder | `config/cobblemon_hms.json` (generated by the mod; the pack ships none yet) | Rock Smash mines any ore, whatever pickaxe the player has. HMs' `minLevel` is the player's XP level, not the Pokémon's |
| Level pressure | full experience up to 5 levels above the zone's band, then 10 % less per level, at least 10 % (Exp. Candy and commands exempt) | Decided (Adrian, 2026-10-30) | `world/zones.json` → `level_pressure` | E.g. on Button Isle (up to Lv 10): Lv 15 full, Lv 20 half, Lv 24+ a tenth | | Level pressure | full experience up to 5 levels above the zone's band, then 10 % less per level, at least 10 % (Exp. Candy and commands exempt) | Decided (Adrian, 2026-10-30) | `world/zones.json` → `level_pressure` | E.g. on Button Isle (up to Lv 10): Lv 15 full, Lv 20 half, Lv 24+ a tenth |
| Strong flyer | ridable through the air with top speed ≥ 60 or top stamina ≥ 85 (Cobblemon ride stats) | Decided (Adrian, 2026-10-30) | `tools/zone_spawns.py` (`STRONG_FLYER_*`) | 29 species | | Strong flyer | ridable through the air with top speed ≥ 60 or top stamina ≥ 85 (Cobblemon ride stats) | Decided (Adrian, 2026-10-30) | `tools/zone_spawns.py` (`STRONG_FLYER_*`) | 29 species |
| High zone for strong flyers | band starts at Lv 30 or more (Sunscorch, Frostpeak, Deep Sea, Deep Dark, Basalt Furnace) | Decided (Adrian, 2026-10-30) | `tools/zone_spawns.py` (`HIGH_ZONE_LEVEL`) | | | High zone for strong flyers | band starts at Lv 30 or more (Sunscorch, Frostpeak, Deep Sea, Deep Dark, Basalt Furnace) | Decided (Adrian, 2026-10-30) | `tools/zone_spawns.py` (`HIGH_ZONE_LEVEL`) | |
+23
View File
@@ -0,0 +1,23 @@
# Phase 5 – checks for Adrian
## Decided
**2026-10-31:** the field moves come from Cobblemon HMs instead of our own system. Mining ore is the one hard requirement, the other moves are nice to have. Furnaces are lit by putting a Pokémon inside a Phase 6 machine, not by a field move. Details: `docs/design.md` → "Phase 5: field moves from Cobblemon HMs".
## Built so far
- **Cobblemon HMs** 4.1.0 is in the pack with its default config (39 abilities, all on).
- **Rock Smash mines the island's ore:** the ore drops, and mined vein blocks turn into regenerators that grow back. Automated: `rock_smash_mines_veins`.
- **HMs' Trainer Ditto** (a visiting TM seller that is a wild Ditto underneath) neither hunts weak trainers nor despawns as a stray.
## In game (Prism instance)
- [ ] Send out a Pokémon that knows Rock Smash, pick Rock Smash on its interaction wheel, and punch an ore node: the node breaks in one go, drops its ore and turns into a regenerator.
- [ ] Do the same on an underground vein that needs a better pickaxe than the one you hold (e.g. iron in Westmarch with no pickaxe): it still breaks.
- [ ] Look at the other abilities your Pokémon offer on the wheel (Cut, Flash, Strength, Surf boosts, ...) and note any you want switched off or tuned.
## Ask Adrian: Phase 5 decisions
1. **Progression.** HMs' abilities all work from the start. Should some wait for guardians like Cobblebase's skills (Rock Smash after an early one, so tiers still matter at first)? HMs' own `minLevel` is the *player's* XP level, which the island doesn't use otherwise.
2. **Zone hazards.** Some abilities get around them: Flash (night vision, lights up the Deep Dark), Lava Plume (fire immunity and walking on lava in the Basalt Furnace), Magnet Rise (flying), Lucky Chant (more ore). Leave them on, switch them off, or gate them behind the zone's guardian?
3. **Party passives.** The roadmap's other half (e.g. Haste with a Rock type, warmth from a Fire type in Frostpeak; your idea of effects from shoulder Pokémon). Still wanted on top of HMs' auras?
+10
View File
@@ -179,6 +179,16 @@ The roadmap lists four mods as prior art; on Cobblemon 1.8 / NeoForge 1.21.1 tod
- [Cobblemon Environment Interactions](https://modrinth.com/project/cobblemon-environment-interactions) 3.1.0 (NeoForge, Apache-2.0, Cobblemon ≥ 1.7.3): type-based mining and utilities while riding or commanding one companion; not move-based. - [Cobblemon Environment Interactions](https://modrinth.com/project/cobblemon-environment-interactions) 3.1.0 (NeoForge, Apache-2.0, Cobblemon ≥ 1.7.3): type-based mining and utilities while riding or commanding one companion; not move-based.
- Cobblemon Field Moves (Fabric, Cobblemon 1.6), Cobblemon Map Kit (Fabric), SceneBlocks (special blocks, custom license), CobbleStrike (real-time attacks): no fit. - Cobblemon Field Moves (Fabric, Cobblemon 1.6), Cobblemon Map Kit (Fabric), SceneBlocks (special blocks, custom license), CobbleStrike (real-time attacks): no fit.
## Phase 5: field moves from Cobblemon HMs (Adrian, 2026-10-31)
Adrian: use Cobblemon HMs. Mining ore is the one hard requirement; the other field moves are nice to have, and Flamethrower in the roadmap was only an example. Furnaces are not lit by a field move: a Pokémon goes *inside* a Phase 6 multiblock instead. So the companion mod doesn't build the roadmap's own `field_moves` system for now; HMs replaces it.
- **Mining** is HMs' Rock Smash: with a Pokémon that knows it sent out, the player's fist breaks the ore it hits and the ore connected to it, up to 32 blocks (power 32). HMs breaks each block as the player with a netherite pickaxe, through the normal break event, so Regenerating Ore Veins turns mined vein blocks into regenerators and the vein grows back. Automated: `rock_smash_mines_veins` (fires HMs' own Rock Smash handler at a vein).
- **Trainer Ditto.** HMs sends a visiting Trainer Ditto that sells TMs; underneath it is a wild Cobblemon Ditto. The island's wild-Pokémon rules (hunting weaker trainers, strays despawning) leave it alone, like guardians (`world/SpecialPokemon.kt`).
- **Config:** HMs' defaults for now (`config/cobblemon_hms.json` is written by the mod on first start; the pack ships none). Every ability can be switched off or tuned there.
Open, for Adrian (`docs/checklists/phase-5.md`): whether HMs' abilities wait for progression like Cobblebase's skills, what to do about the ones that get around zone hazards, and whether party passives (shoulder Pokémon) are still wanted.
## Notes for Phase 6 (researched 2026-10-31) ## Notes for Phase 6 (researched 2026-10-31)
Adrian asked for existing mods for the multiblocks, or at least their logic. Phase 6's machines need a pattern-checked structure with a controller, a Pokémon stored inside (keeping its data, visible), safe return when the structure breaks, and state that survives unload and restart. Power is already Poke Power's (Phase 4), so the first machine is the Large Furnace. Nothing on NeoForge 1.21.1 puts a Pokémon into a multiblock; the structure part has several options: Adrian asked for existing mods for the multiblocks, or at least their logic. Phase 6's machines need a pattern-checked structure with a controller, a Pokémon stored inside (keeping its data, visible), safe return when the structure breaks, and state that survives unload and restart. Power is already Poke Power's (Phase 4), so the first machine is the Large Furnace. Nothing on NeoForge 1.21.1 puts a Pokémon into a multiblock; the structure part has several options:
+1
View File
@@ -42,6 +42,7 @@ Read each license before adding a mod, and add a row here in the same change.
| Cold Sweat | Momo Softworks (Mikul) | GPL-3.0-or-later | [Modrinth](https://modrinth.com/mod/cold-sweat) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/cold-sweat) | Phase 3: heat and cold as zone hazards (both) | | Cold Sweat | Momo Softworks (Mikul) | GPL-3.0-or-later | [Modrinth](https://modrinth.com/mod/cold-sweat) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/cold-sweat) | Phase 3: heat and cold as zone hazards (both) |
| Cobblebase | notlown | MPL-2.0 | [Modrinth](https://modrinth.com/project/cobblebase) | Phase 4: Pokémon jobs at the base (both). The 1.8 build is Modrinth only | | Cobblebase | notlown | MPL-2.0 | [Modrinth](https://modrinth.com/project/cobblebase) | Phase 4: Pokémon jobs at the base (both). The 1.8 build is Modrinth only |
| Cobblemon Poke Power | Matthiesen-dev (Adammatthiesen) | MIT | [Modrinth](https://modrinth.com/project/lIn7oRFm) | Phase 4: Pokémon-powered Forge Energy (both). Not on CurseForge | | Cobblemon Poke Power | Matthiesen-dev (Adammatthiesen) | MIT | [Modrinth](https://modrinth.com/project/lIn7oRFm) | Phase 4: Pokémon-powered Forge Energy (both). Not on CurseForge |
| Cobblemon HMs | shiero | shiero's Mods License (in the jar): free to use, also in free modpacks; any monetized use (paid pack, paid server perks) needs an agreement with the author | [Modrinth](https://modrinth.com/project/cobblemon-hms) | Phase 5: field moves (both). Not resolved on CurseForge yet |
| Regenerating Ore Veins | Stargazer | MIT (jar metadata) | [CurseForge](https://www.curseforge.com/minecraft/mc-mods/regenerating-ore-veins) | Phase 4: the only ore source besides chest loot (both). Not on Modrinth | | Regenerating Ore Veins | Stargazer | MIT (jar metadata) | [CurseForge](https://www.curseforge.com/minecraft/mc-mods/regenerating-ore-veins) | Phase 4: the only ore source besides chest loot (both). Not on Modrinth |
| WorldGen Editor | waterflane | CC BY-NC-SA 4.0 | [Modrinth](https://modrinth.com/mod/worldgen-editor) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/worldgen-editor), [source](https://github.com/waterflane/WorldGen-Editor) | Non-commercial, share-alike. See the derived files below | | WorldGen Editor | waterflane | CC BY-NC-SA 4.0 | [Modrinth](https://modrinth.com/mod/worldgen-editor) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/worldgen-editor), [source](https://github.com/waterflane/WorldGen-Editor) | Non-commercial, share-alike. See the derived files below |
+2
View File
@@ -132,6 +132,8 @@ Goal: ore, Pokémon drops and base production form the economy.
Goal: moves a Pokémon knows act on the world, HM-style. Flamethrower sets blocks on fire. Goal: moves a Pokémon knows act on the world, HM-style. Flamethrower sets blocks on fire.
**Decided 2026-10-31 (Adrian):** the field moves come from Cobblemon HMs instead of the spec below; mining ore is the one hard requirement, and furnaces are lit by a Pokémon inside a Phase 6 machine. See `docs/design.md`.
**Prior art to study, not depend on.** None is confirmed on Cobblemon 1.8: **Prior art to study, not depend on.** None is confirmed on Cobblemon 1.8:
- [Cobblemon Field Survival](https://www.modpackindex.com/mod/173947/cobblemon-field-survival) (NeoForge 1.21.1, Cobblemon 1.7.3): mining, digging, water utilities, Fire types cooking food. - [Cobblemon Field Survival](https://www.modpackindex.com/mod/173947/cobblemon-field-survival) (NeoForge 1.21.1, Cobblemon 1.7.3): mining, digging, water utilities, Fire types cooking food.
@@ -9,6 +9,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.JsonElement import com.google.gson.JsonElement
import dev.cobblesurvival.CobbleSurvival import dev.cobblesurvival.CobbleSurvival
import dev.cobblesurvival.world.SpecialPokemon
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.resources.ResourceManager import net.minecraft.server.packs.resources.ResourceManager
@@ -23,7 +24,8 @@ import net.neoforged.neoforge.event.tick.ServerTickEvent
* strongest party Pokémon: * strongest party Pokémon:
* - the catch rate falls with the level gap, down to a small share at 20 levels above ("very improbable"); * - the catch rate falls with the level gap, down to a small share at 20 levels above ("very improbable");
* - a Pokémon that breaks out of a ball attacks the thrower instead of fleeing; * - a Pokémon that breaks out of a ball attacks the thrower instead of fleeing;
* - a wild Pokémon above a nearby player's strongest Pokémon is hostile to that player. * - a wild Pokémon above a nearby player's strongest Pokémon is hostile to that player (not guardians and other
* special Pokémon, see [SpecialPokemon]).
* *
* The attacking is Fight or Flight Reborn's: an angry Pokémon carries the aspect [ENRAGED], which the pack's Fight or * The attacking is Fight or Flight Reborn's: an angry Pokémon carries the aspect [ENRAGED], which the pack's Fight or
* Flight config lists in `always_aggro_aspects` (so it fights rather than flees), and its target is set through Fight * Flight config lists in `always_aggro_aspects` (so it fights rather than flees), and its target is set through Fight
@@ -96,7 +98,7 @@ object Catching : SimpleJsonResourceReloadListener(Gson(), "catching") {
val strongest = strongest(player) val strongest = strongest(player)
val near = player.boundingBox.inflate(rules.hostileRange) val near = player.boundingBox.inflate(rules.hostileRange)
player.serverLevel().getEntitiesOfClass(PokemonEntity::class.java, near) { player.serverLevel().getEntitiesOfClass(PokemonEntity::class.java, near) {
it.pokemon.isWild() && !it.isBattling && it.pokemon.level > strongest it.pokemon.isWild() && !it.isBattling && it.pokemon.level > strongest && !SpecialPokemon.isExempt(it.pokemon)
}.forEach { enrage(it, player) } }.forEach { enrage(it, player) }
} }
} }
@@ -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() = private val cases: List<SelfTestCase> get() =
PermadeathTests.all() + SurvivalRulesTests.all() + ZoneTests.all() + HazardTests.all() + GuardianTests.all() + PermadeathTests.all() + SurvivalRulesTests.all() + ZoneTests.all() + HazardTests.all() + GuardianTests.all() +
VeinTests.all() + OreNodeTests.all() + DropTests.all() + ProgressionTests.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 running: List<Scenario> = emptyList()
private var forced: List<ChunkPos> = emptyList() private var forced: List<ChunkPos> = emptyList()
@@ -0,0 +1,17 @@
package dev.cobblesurvival.world
import com.cobblemon.mod.common.pokemon.Pokemon
import dev.cobblesurvival.zone.Guardians
/**
* Wild Pokémon that the island's rules for wild Pokémon (strays despawning, hunting weaker trainers) leave alone:
* guardians, anything uncatchable, and other mods' characters that are Pokémon underneath, such as Cobblemon HMs'
* visiting Trainer Ditto, which sells TMs.
*/
object SpecialPokemon {
/** Cobblemon HMs marks its Trainer Ditto with this in the Pokémon's persistent data. */
private const val HMS_TRAINER = "dittohms_trainer"
fun isExempt(pokemon: Pokemon): Boolean =
pokemon.isUncatchable() || pokemon.persistentData.contains(Guardians.TAG) || pokemon.persistentData.contains(HMS_TRAINER)
}
@@ -1,6 +1,7 @@
package dev.cobblesurvival.zone package dev.cobblesurvival.zone
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import dev.cobblesurvival.world.SpecialPokemon
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.ai.memory.MemoryModuleType import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.neoforged.neoforge.common.NeoForge import net.neoforged.neoforge.common.NeoForge
@@ -11,7 +12,8 @@ import java.util.UUID
* Wild Pokémon keep to their zone's levels (Adrian, 2026-10-30: a Lv 61 Pokémon from the Basalt Furnace turned up in the * Wild Pokémon keep to their zone's levels (Adrian, 2026-10-30: a Lv 61 Pokémon from the Basalt Furnace turned up in the
* Lush Caves, Lv 12–28). Spawns follow the zones, but wild Pokémon wander and cave zones touch, so every few seconds a * Lush Caves, Lv 12–28). Spawns follow the zones, but wild Pokémon wander and cave zones touch, so every few seconds a
* wild Pokémon near a player that stands in a zone whose band it tops by more than [Zones.wanderGrace] levels * wild Pokémon near a player that stands in a zone whose band it tops by more than [Zones.wanderGrace] levels
* despawns, unless it is in a battle, angry at someone (it is chasing them) or a guardian. Grace: world/zones.json → * despawns, unless it is in a battle, angry at someone (it is chasing them), a guardian or another special Pokémon
* ([SpecialPokemon]). Grace: world/zones.json →
* `wanderers`. * `wanderers`.
*/ */
object Wanderers { object Wanderers {
@@ -38,7 +40,7 @@ object Wanderers {
} }
fun strayed(level: ServerLevel, wild: PokemonEntity, grace: Int): Boolean { fun strayed(level: ServerLevel, wild: PokemonEntity, grace: Int): Boolean {
if (wild.isBattling || wild.pokemon.persistentData.contains(Guardians.TAG)) return false if (wild.isBattling || SpecialPokemon.isExempt(wild.pokemon)) return false
if (wild.brain.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) return false if (wild.brain.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) return false
val zone = Zones.at(level, wild.blockPosition()) ?: return false val zone = Zones.at(level, wild.blockPosition()) ?: return false
return wild.pokemon.level > zone.maxLevel + grace return wild.pokemon.level > zone.maxLevel + grace
+5
View File
@@ -126,6 +126,11 @@ file = "mods/cobblemon-fight-or-flight-reborn.pw.toml"
hash = "227eea45819938ae2e0911d825e9ccf0e0236b1a36e46627204d8aa53becc9e7" hash = "227eea45819938ae2e0911d825e9ccf0e0236b1a36e46627204d8aa53becc9e7"
metafile = true metafile = true
[[files]]
file = "mods/cobblemon-hms.pw.toml"
hash = "36f7da26797651777c39409f5e8b2aeb2fe8b7d59a0a62a791a9c6b2c2d318e8"
metafile = true
[[files]] [[files]]
file = "mods/cobblemon-poke-power.pw.toml" file = "mods/cobblemon-poke-power.pw.toml"
hash = "29ccd4c39e5af1a2fb63a40bf67ecd03bcced42e9e1edf296b26fd1847740a54" hash = "29ccd4c39e5af1a2fb63a40bf67ecd03bcced42e9e1edf296b26fd1847740a54"
+13
View File
@@ -0,0 +1,13 @@
name = "Cobblemon HMs"
filename = "cobblemon-hms-neoforge-4.1.0.jar"
side = "both"
[download]
url = "https://cdn.modrinth.com/data/JNfSyMuQ/versions/uC02CqRy/cobblemon-hms-neoforge-4.1.0.jar"
hash-format = "sha512"
hash = "009f1a6deb011ffa42f29bb784a7de5ddd0233b38da0885e6f8aa70ce5a07c961f853ad5807dd6706f756e191751faf2f096f1df9331c652ca8254302979d437"
[update]
[update.modrinth]
mod-id = "JNfSyMuQ"
version = "uC02CqRy"
+1 -1
View File
@@ -6,7 +6,7 @@ pack-format = "packwiz:1.1.0"
[index] [index]
file = "index.toml" file = "index.toml"
hash-format = "sha256" hash-format = "sha256"
hash = "36704b01cdb1201d353d8987ebaa4ecb8b1bee8a4ea5352dfc9c14e9472f764a" hash = "d8359ad9c1f98c8c72503f0ce16773d7721a1a4095cfdef15ca3e985736ae6ff"
[versions] [versions]
minecraft = "1.21.1" minecraft = "1.21.1"