Compare commits

..
Author SHA1 Message Date
whatsy 087a167bfa ...and then make that PlatformRegistry actually work 2026-10-30 15:18:54 -04:00
whatsy 461d21a87d Convert CobblemonLootItemConditions into a PlatformRegistry 2026-10-30 14:48:30 -04:00
whatsy 78953357a8 Pokedex compat 2026-10-30 14:39:38 -04:00
whatsy bdfabb3724 Update CHANGELOG.md + resolve merge conflicts 2026-10-27 23:54:56 -04:00
whatsy 3adb6144a3 Merge branch 'refs/heads/main' into drop-system-update
# Conflicts:
#	common/src/main/resources/data/cobblemon/species/generation1/exeggutor.json
#	common/src/main/resources/data/cobblemon/species/generation4/rotom.json
#	common/src/main/resources/data/cobblemon/species/generation4/wormadam.json
#	common/src/main/resources/data/cobblemon/species/generation5/kyurem.json
#	common/src/main/resources/data/cobblemon/species/generation6/avalugg.json
#	common/src/main/resources/data/cobblemon/species/generation6/flabebe.json
#	common/src/main/resources/data/cobblemon/species/generation6/floette.json
#	common/src/main/resources/data/cobblemon/species/generation6/florges.json
#	common/src/main/resources/data/cobblemon/species/generation6/goodra.json
#	common/src/main/resources/data/cobblemon/species/generation6/greninja.json
#	common/src/main/resources/data/cobblemon/species/generation6/sliggoo.json
#	common/src/main/resources/data/cobblemon/species/generation7/decidueye.json
#	common/src/main/resources/data/cobblemon/species/generation8/toxtricity.json
2026-10-27 23:48:49 -04:00
whatsy 65bcd118a3 finalizing 2026-10-21 13:25:46 -04:00
whatsy bf6f97e740 auto fire aspect support 2026-10-21 12:25:24 -04:00
whatsy 4e48e2ff9b scraper updates 2026-10-20 18:43:01 -04:00
whatsy faa488b153 ported all pokemon over to loot tables 2026-10-19 17:09:20 -04:00
whatsy 93dbc015fb loot table drop entry type implementation 2026-10-19 13:49:34 -04:00
whatsy 7edf6669d8 Vanilla loot tables for pokemon drops: wip, pushing for review 2026-10-19 11:52:44 -04:00
2221 changed files with 90385 additions and 10253 deletions

No files matched your search

+18 -5
View File
@@ -1,15 +1,28 @@
# Changelog
## [1.8.x (MONTH xth, 2026)](#1-8-x)
## [1.8.5 (MONTH xth, 2026)](#1-8-5)
### Additions
### Particles
### Cries added/updated for the following Pokémon
### Model updates for the following Pokémon
### Animation updates for the following Pokémon
### Changes
### Fixes
### Developer
### Molang & Datapacks
- Added a `loot_table` drop entry type.
- Accepts an `id` field, pointing to a vanilla loot table.
- All base mod Pokémon have been moved to this new system.
- Added the `cobblemon:biome` and `cobblemon:pokemon_properties` loot conditions.
- `cobblemon:biome` returns true if the biome of death matches the `biome` field.
- `cobblemon:pokemon_properties` returns true if the Pokémon matches the `properties` field.
### Particles
### Localization
- Updated translations for:
### Localization
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.drop.CommandDropEntry
import com.cobblemon.mod.common.api.drop.DropEntry
import com.cobblemon.mod.common.api.drop.EvolutionItemDropEntry
import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.drop.LootTableDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
import com.cobblemon.mod.common.api.habitats.HabitatPools
@@ -90,6 +91,7 @@ import com.cobblemon.mod.common.events.EntityCallbackHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.events.StatHandler
import com.cobblemon.mod.common.loot.CobblemonLootItemConditions
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
@@ -225,10 +227,12 @@ object Cobblemon {
implementation.registerEntitySubPredicates()
implementation.registerMobEffects()
DispenserBehaviorRegistry.registerDispenserBehaviors()
CobblemonLootItemConditions.touch()
DropEntry.register("command", CommandDropEntry::class.java)
DropEntry.register("item", ItemDropEntry::class.java, isDefault = true)
DropEntry.register("evolution", EvolutionItemDropEntry::class.java)
DropEntry.register("loot_table", LootTableDropEntry::class.java)
ExperienceGroups.registerDefaults()
CaptureCalculators.registerDefaults()
@@ -118,6 +118,7 @@ interface CobblemonImplementation {
fun registerMenu()
fun registerEntitySubPredicates()
fun registerLootItemConditions()
/**
* TODO
@@ -42,14 +42,9 @@ import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.orientation.ClientboundUpdateOrientationHandler
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureRangeHandler
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureRangePacket
import com.cobblemon.mod.common.net.messages.server.pasture.AdjustPastureRangePacket
import com.cobblemon.mod.common.net.serverhandling.pasture.AdjustPastureRangeHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureRecoveryHandler
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundSeatAssignmentPacketHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
@@ -106,7 +101,6 @@ import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureRecoveryPacket
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
@@ -479,12 +473,10 @@ object CobblemonNetwork {
// Pasture
list.add(PacketRegisterInfo(OpenPasturePacket.ID, OpenPasturePacket::decode, OpenPastureHandler))
list.add(PacketRegisterInfo(UpdatePastureRangePacket.ID, UpdatePastureRangePacket::decode, UpdatePastureRangeHandler))
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
list.add(PacketRegisterInfo(UpdatePastureRecoveryPacket.ID, UpdatePastureRecoveryPacket::decode, UpdatePastureRecoveryHandler))
// Orientation
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, ClientboundUpdateOrientationHandler))
@@ -599,7 +591,6 @@ object CobblemonNetwork {
// Pasture
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
list.add(PacketRegisterInfo(AdjustPastureRangePacket.ID, AdjustPastureRangePacket::decode, AdjustPastureRangeHandler))
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
list.add(PacketRegisterInfo(SetPastureConflictPacket.ID, SetPastureConflictPacket::decode, SetPastureConflictHandler))
@@ -666,4 +657,4 @@ object CobblemonNetwork {
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
}
}
}
@@ -15,13 +15,11 @@ import com.cobblemon.mod.common.api.ai.asVariables
import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WANDER
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.withQueryValue
import com.mojang.datafixers.util.Either
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BehaviorControl
@@ -71,14 +69,7 @@ class AirWanderTaskConfig : SingleTaskConfig {
val rotVec = entity.getViewVector(0F)
pathCooldown.setWithExpiry(true, 60L)
val tethering = (entity as? PokemonEntity)?.tethering
val horizontal = horizontalRange.resolveInt(runtime)
val vertical = verticalRange.resolveInt(runtime)
val minUpwards = minUpwardsMovement.resolveInt(runtime)
val minDownwards = minDownwardsMovement.resolveInt(runtime)
val target = (0 until 10).asSequence()
.mapNotNull { HoverRandomPos.getPos(entity, horizontal, vertical, rotVec.x, rotVec.y, 1.5707964f, minUpwards, minDownwards) }
.firstOrNull { tethering?.canRoamTo(BlockPos.containing(it)) != false }
val target = HoverRandomPos.getPos(entity, horizontalRange.resolveInt(runtime), verticalRange.resolveInt(runtime), rotVec.x, rotVec.y, 1.5707964f, minUpwardsMovement.resolveInt(runtime), minDownwardsMovement.resolveInt(runtime))
?: return@Trigger false
walkTarget.set(WalkTarget(target, speedMultiplier.resolveFloat(runtime), 3))
lookTarget.set(BlockPosTracker(target))
@@ -87,4 +78,4 @@ class AirWanderTaskConfig : SingleTaskConfig {
}
}
}
}
}
@@ -17,7 +17,6 @@ import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WA
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveFloat
@@ -96,7 +95,6 @@ class WaterWanderTaskConfig : SingleTaskConfig {
attempts++
target = BehaviorUtils.getRandomSwimmablePos(entity, horizontalRange.resolveInt(mainThreadRuntime), verticalRange.resolveInt(mainThreadRuntime))
?: continue
if ((entity as? PokemonEntity)?.tethering?.canRoamTo(BlockPos.containing(target)) == false) continue
pos = BlockPos.containing(target).takeIf(wanderControl::isSuitable)
}
@@ -145,4 +143,4 @@ class WaterWanderTaskConfig : SingleTaskConfig {
}
}
}
}
}
@@ -10,9 +10,14 @@ package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.registries.Registries
import kotlin.random.Random
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
@@ -105,7 +110,11 @@ class DropTable {
) {
LOOT_DROPPED.postThen(
event = LootDroppedEvent(this, player, entity, drops),
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
ifSucceeded = {
val pokemon = (entity as? PokemonEntity)?.pokemon?.species?.resourceIdentifier ?: return@postThen
it.drops.forEach { it.drop(entity, world, pos, player) }
// val lootKey = ResourceKey.create(Registries.LOOT_TABLE, cobblemonResource("pokemon/${pokemon}"))
}
)
}
@@ -0,0 +1,64 @@
package com.cobblemon.mod.common.api.drop
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.level.storage.loot.LootParams
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.phys.Vec3
/**
* A drop entry that points to a vanilla loot table.
*/
class LootTableDropEntry(
override var percentage: Float,
override var quantity: Int,
override var maxSelectableTimes: Int,
val id: ResourceLocation
) : DropEntry {
override fun drop(
entity: LivingEntity?,
world: ServerLevel,
pos: Vec3,
player: ServerPlayer?
) {
val key = ResourceKey.create(Registries.LOOT_TABLE, id)
val playerEntity = player as? LivingEntity
if (entity == null) return
if (playerEntity != null) {
val params = LootParams.Builder(world)
.withParameter(LootContextParams.ATTACKING_ENTITY, playerEntity)
.withParameter(LootContextParams.DAMAGE_SOURCE, playerEntity.damageSources().genericKill())
.withParameter(LootContextParams.ORIGIN, pos)
.withParameter(LootContextParams.THIS_ENTITY, entity)
.create(LootContextParamSets.ENTITY)
val drops = world.server.reloadableRegistries().getLootTable(key)
.getRandomItems(params)
for (stack in drops) {
if (stack.isEmpty) continue
val itemEntity = ItemEntity(world, pos.x, pos.y, pos.z, stack)
itemEntity.setDefaultPickUpDelay()
world.addFreshEntity(itemEntity)
}
} else {
val params = LootParams.Builder(world)
.create(LootContextParamSets.EMPTY)
val drops = world.server.reloadableRegistries().getLootTable(key)
.getRandomItems(params)
for (stack in drops) {
if (stack.isEmpty) continue
val itemEntity = ItemEntity(world, pos.x, pos.y, pos.z, stack)
itemEntity.setDefaultPickUpDelay()
world.addFreshEntity(itemEntity)
}
}
}
}
@@ -34,7 +34,7 @@ object PastureLinkManager {
fun getLinkByPlayer(player: ServerPlayer): PastureLink? {
val link = getLinkByPlayerId(player.uuid)
if (link != null) {
if (player.level().dimension().location() != link.dimension || !link.pos.closerToCenterThan(player.position(), 10.0)) {
if (!player.level().dimensionTypeRegistration().`is`(link.dimension) || !link.pos.closerToCenterThan(player.position(), 10.0)) {
links.remove(player.uuid)
return null
}
@@ -46,8 +46,8 @@ object PastureLinkManager {
@JvmStatic
fun removeAt(world: ServerLevel, pos: BlockPos) {
links.removeIf { (uuid, pastureLink) ->
val shouldRemove = world.dimension().location() == pastureLink.dimension && pastureLink.pos == pos
if (shouldRemove) uuid.getPlayer()?.sendPacket(ClosePasturePacket())
val shouldRemove = world.dimensionTypeRegistration().`is`(pastureLink.dimension) && pastureLink.pos == pos
uuid.getPlayer()?.sendPacket(ClosePasturePacket())
return@removeIf shouldRemove
}
}
@@ -1,82 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pasture
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.network.RegistryFriendlyByteBuf
import kotlin.math.abs
import kotlin.math.ceil
import kotlin.math.floor
data class PastureRange(val north: Int, val east: Int, val south: Int, val west: Int) {
fun isValid(maximum: Int): Boolean =
listOf(north, east, south, west).all { it in 0..maximum } &&
north.toLong() + south >= 8 && east.toLong() + west >= 8
operator fun get(direction: Direction): Int = when (direction) {
Direction.NORTH -> north
Direction.EAST -> east
Direction.SOUTH -> south
Direction.WEST -> west
else -> error("Pasture range directions must be horizontal")
}
fun adjusted(direction: Direction, amount: Int): PastureRange = when (direction) {
Direction.NORTH -> copy(north = north + amount)
Direction.EAST -> copy(east = east + amount)
Direction.SOUTH -> copy(south = south + amount)
Direction.WEST -> copy(west = west + amount)
else -> this
}
fun minPos(origin: BlockPos) = origin.offset(-west, 0, -north)
fun maxPos(origin: BlockPos) = origin.offset(east, 0, south)
fun nearbyBlocks(origin: BlockPos, preferred: BlockPos, width: Double): Sequence<BlockPos> = sequence {
val halfWidth = width / 2.0
val minX = ceil(origin.x - west + halfWidth - 0.5).toInt()
val maxX = floor(origin.x + east - halfWidth - 0.5).toInt()
val minZ = ceil(origin.z - north + halfWidth - 0.5).toInt()
val maxZ = floor(origin.z + south - halfWidth - 0.5).toInt()
if (minX > maxX || minZ > maxZ) return@sequence
val centerX = preferred.x.coerceIn(minX, maxX)
val centerZ = preferred.z.coerceIn(minZ, maxZ)
for (distance in 0..16) {
for (dx in -distance..distance) {
val x = centerX + dx
if (x !in minX..maxX) continue
val dz = distance - abs(dx)
val z = centerZ + dz
if (z in minZ..maxZ) yield(BlockPos(x, origin.y, z))
if (dz != 0 && centerZ - dz in minZ..maxZ) yield(BlockPos(x, origin.y, centerZ - dz))
}
}
}
fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeVarInt(north)
buffer.writeVarInt(east)
buffer.writeVarInt(south)
buffer.writeVarInt(west)
}
companion object {
const val MAX_DISTANCE = 64
fun fromBounds(origin: BlockPos, min: BlockPos, max: BlockPos) = PastureRange(
origin.z - min.z, max.x - origin.x, max.z - origin.z, origin.x - min.x
)
fun decode(buffer: RegistryFriendlyByteBuf) = PastureRange(
buffer.readVarInt(), buffer.readVarInt(), buffer.readVarInt(), buffer.readVarInt()
)
}
}
@@ -25,6 +25,7 @@ import com.cobblemon.mod.common.util.rotateShape
import com.mojang.serialization.MapCodec
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.util.StringRepresentable
@@ -282,13 +283,11 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
pastureId = linkId,
permissions = perms,
limit = baseEntity.getMaxTethered(),
tetheredPokemon = baseEntity.tetheredPokemon.mapNotNull { it.toDTO(player) },
range = baseEntity.getRange(),
facing = state.getValue(HorizontalDirectionalBlock.FACING)
tetheredPokemon = baseEntity.tetheredPokemon.mapNotNull { it.toDTO(player) }
)
)
PastureLinkManager.createLink(player.uuid, PastureLink(linkId, pcId, world.dimension().location(), getBasePosition(state, pos), perms))
PastureLinkManager.createLink(player.uuid, PastureLink(linkId, pcId, ResourceLocation.tryParse(world.dimensionTypeRegistration().registeredName)!!, getBasePosition(state, pos), perms))
world.playSoundServer(
position = pos.bottomCenter,
@@ -367,4 +366,4 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
return state
}
}
}
@@ -14,19 +14,15 @@ import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.api.pasture.PastureLinkManager
import com.cobblemon.mod.common.api.pasture.PastureRange
import com.cobblemon.mod.common.api.scheduling.afterOnServer
import com.cobblemon.mod.common.api.text.italicise
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.block.PastureBlock
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureRecoveryPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
@@ -43,6 +39,7 @@ import net.minecraft.core.Vec3i
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.NbtUtils
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.tags.FluidTags
@@ -51,61 +48,38 @@ import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.entity.EntityTypeTest
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
BlockEntity(CobblemonBlockEntities.PASTURE, pos, state) {
open class Tethering(
var minRoamPos: BlockPos,
var maxRoamPos: BlockPos,
val minRoamPos: BlockPos,
val maxRoamPos: BlockPos,
val playerId: UUID,
val playerName: String,
val tetheringId: UUID,
val pokemonId: UUID,
val pcId: UUID,
var entityId: Int,
val pasturePos: BlockPos,
var entityUuid: UUID? = null,
var lastEntityPos: BlockPos? = null,
var respawnAt: Long = 0L,
var healingAfterFaint: Boolean = false,
var conflictEnabled: Boolean? = null
val entityId: Int,
val pasturePos: BlockPos
) {
fun getPokemon(): Pokemon? {
val srv = server() ?: return null
val pc = Cobblemon.storage.getPC(pcId, srv.registryAccess())
return pc[pokemonId]
}
val box get() = AABB(minRoamPos.toVec3d(), maxRoamPos.toVec3d())
fun canRoamTo(x: Double, z: Double) = x >= minRoamPos.x && x < maxRoamPos.x && z >= minRoamPos.z && z < maxRoamPos.z
open fun canRoamTo(pos: BlockPos) = canRoamTo(pos.x + 0.5, pos.z + 0.5)
internal fun beginRecovery(now: Long, fainted: Boolean) {
if (fainted && !healingAfterFaint) {
healingAfterFaint = true
respawnAt = now + FAINT_COOLDOWN
} else if (respawnAt == 0L) {
respawnAt = now + MISSING_ENTITY_COOLDOWN
}
}
val box = AABB(minRoamPos.toVec3d(), maxRoamPos.toVec3d())
open fun canRoamTo(pos: BlockPos) = box.contains(pos.center)
fun toDTO(player: ServerPlayer): OpenPasturePacket.PasturePokemonDataDTO? {
val pokemon = getPokemon() ?: return null
val entity = pokemon.entity
val behaviourFlags = (entity?.getActiveBehaviourFlags() ?: emptySet()).toMutableSet()
when (conflictEnabled) {
true -> behaviourFlags.add(PokemonBehaviourFlag.PASTURE_CONFLICT)
false -> behaviourFlags.remove(PokemonBehaviourFlag.PASTURE_CONFLICT)
null -> Unit
}
val behaviourFlags = entity?.getActiveBehaviourFlags() ?: emptySet()
return OpenPasturePacket.PasturePokemonDataDTO(
pokemonId = pokemonId,
@@ -117,16 +91,12 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
heldItem = pokemon.heldItem(),
level = pokemon.level,
entityKnown = (entity?.tethering?.tetheringId == tetheringId),
behaviourFlags = behaviourFlags,
healingAfterFaint = healingAfterFaint,
respawnAt = respawnAt
behaviourFlags = behaviourFlags
)
}
}
companion object {
private const val FAINT_COOLDOWN = 24000L
private const val MISSING_ENTITY_COOLDOWN = 200L
internal val TICKER = BlockEntityTicker<PokemonPastureBlockEntity> { world, _, _, blockEntity ->
if (world.isClientSide) return@BlockEntityTicker
blockEntity.ticksUntilCheck--
@@ -164,26 +134,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
fun getMaxTethered() = Cobblemon.config.defaultPasturedPokemonLimit
fun getRange() = PastureRange.fromBounds(blockPos, minRoamPos, maxRoamPos)
fun setRange(range: PastureRange) {
minRoamPos = range.minPos(blockPos).atY(minRoamPos.y)
maxRoamPos = range.maxPos(blockPos).atY(maxRoamPos.y)
tetheredPokemon.forEach { tethering ->
tethering.minRoamPos = minRoamPos
tethering.maxRoamPos = maxRoamPos
tethering.getPokemon()?.entity?.let { entity ->
if (entity.tethering?.tetheringId == tethering.tetheringId) {
entity.tethering = tethering
entity.navigation.stop()
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET)
entity.checkPastureTether()
}
}
}
setChanged()
}
fun canAddPokemon(player: ServerPlayer, pokemon: Pokemon, maxPerPlayer: Int): Boolean {
val forThisPlayer = tetheredPokemon.count { it.playerId == player.uuid }
// Shouldn't be possible, client should've prevented it
@@ -208,64 +158,57 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
fun tether(player: ServerPlayer, pokemon: Pokemon, directionToBehind: Direction): Boolean {
val tethering = Tethering(
minRoamPos, maxRoamPos, player.uuid, player.gameProfile.name, UUID.randomUUID(),
pokemon.uuid, Cobblemon.storage.getPC(player).uuid, -1, blockPos
)
if (!spawnPokemon(pokemon, tethering, directionToBehind)) return false
pokemon.tetheringId = tethering.tetheringId
pokemon.onChange()
tetheredPokemon.add(tethering)
tethering.toDTO(player)?.let { player.sendPacket(PokemonPasturedPacket(it)) }
setChanged()
CobblemonCriteria.PASTURE_USE.trigger(player, pokemon)
return true
}
private fun spawnPokemon(pokemon: Pokemon, tethering: Tethering, directionToBehind: Direction): Boolean {
val world = level ?: return false
val entity = PokemonEntity(world, pokemon = pokemon)
entity.refreshDimensions()
val position = findSpawnPosition(entity, tethering.lastEntityPos, directionToBehind) ?: return false
entity.setPos(position)
entity.beamMode = 2
entity.tethering = tethering
entity.setBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT, tethering.conflictEnabled == true)
if (!world.addFreshEntity(entity)) return false
if (tethering.conflictEnabled == true) entity.remakeBrain()
tethering.entityId = entity.id
tethering.entityUuid = entity.uuid
tethering.lastEntityPos = entity.blockPosition()
tethering.respawnAt = 0L
syncRecovery(tethering)
afterOnServer(seconds = 0.5F) {
if (!entity.isRemoved && entity.pokemon.shiny) {
SpawnSnowstormEntityParticlePacket(cobblemonResource("shiny_ring"), entity.id, listOf("shiny_particles", "middle"))
.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
}
entity.after(seconds = SendOutPokemonHandler.SEND_OUT_DURATION) {
entity.beamMode = 0
}
}
return true
}
val width = entity.boundingBox.xsize
fun findSpawnPosition(entity: PokemonEntity, preferred: BlockPos? = null, direction: Direction = blockState.getValue(HorizontalDirectionalBlock.FACING)): Vec3? {
val world = level ?: return null
val dimensions = entity.getDimensions(Pose.STANDING)
val idealPlace = preferred ?: blockPos.offset(direction.normal.multiply(ceil(dimensions.width / 2.0).toInt() + 1))
for (candidate in getRange().nearbyBlocks(blockPos, idealPlace, dimensions.width.toDouble())) {
if (!world.hasChunkAt(candidate)) continue
val box = dimensions.makeBoundingBox(candidate.center.subtract(0.0, 0.5, 0.0))
val fixedPosition = makeSuitableY(world, candidate, entity, box) ?: continue
val position = fixedPosition.center.subtract(0.0, 0.5, 0.0)
val spawnBox = dimensions.makeBoundingBox(position)
if (world.noCollision(entity, spawnBox) &&
world.getEntitiesOfClass(PokemonEntity::class.java, spawnBox) { it != entity }.isEmpty()) {
return position
val idealPlace = blockPos.offset(directionToBehind.normal.multiply(ceil(width).toInt() + 1))
var box = entity.getDimensions(Pose.STANDING).makeBoundingBox(idealPlace.center.subtract(0.0, 0.5, 0.0))
for (i in 0..5) {
box = box.move(directionToBehind.normal.x.toDouble(), 0.0, directionToBehind.normal.z.toDouble())
val fixedPosition = makeSuitableY(world, idealPlace.offset(directionToBehind.normal.multiply(i + 1)), entity, box)
if (fixedPosition != null) {
entity.setPos(fixedPosition.center.subtract(0.0, 0.5, 0.0))
val pc = Cobblemon.storage.getPC(player)
entity.beamMode = 2
afterOnServer(seconds = 0.5F) {
if(entity.pokemon.shiny) {
SpawnSnowstormEntityParticlePacket(cobblemonResource("shiny_ring"), entity.id, listOf("shiny_particles", "middle"))
.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
}
entity.after(seconds = SendOutPokemonHandler.SEND_OUT_DURATION) {
entity.beamMode = 0
}
}
if (world.addFreshEntity(entity)) {
val tethering = Tethering(
minRoamPos = minRoamPos,
maxRoamPos = maxRoamPos,
playerId = player.uuid,
playerName = player.gameProfile.name,
tetheringId = UUID.randomUUID(),
pokemonId = pokemon.uuid,
pcId = pc.uuid,
entityId = entity.id,
pasturePos = blockPos
)
pokemon.tetheringId = tethering.tetheringId
tetheredPokemon.add(tethering)
entity.tethering = tethering
tethering.toDTO(player)?.let { player.sendPacket(PokemonPasturedPacket(it)) }
setChanged()
CobblemonCriteria.PASTURE_USE.trigger(player, pokemon)
return true
} else {
Cobblemon.LOGGER.warn("Couldn't spawn pastured Pokémon for some reason")
}
break
}
}
return null
return false
}
private fun togglePastureOn(on: Boolean) {
@@ -346,7 +289,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
}
fun checkPokemon() {
val world = level as? ServerLevel ?: return
val deadLinks = mutableListOf<UUID>()
tetheredPokemon.forEach {
val pokemon = it.getPokemon()
@@ -354,8 +296,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
deadLinks.add(it.pokemonId)
} else if (pokemon.tetheringId == null || pokemon.tetheringId != it.tetheringId) {
deadLinks.add(it.pokemonId)
} else {
checkDeployment(world, it, pokemon)
}
}
deadLinks.forEach(::releasePokemon)
@@ -363,85 +303,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
setChanged()
}
private fun checkDeployment(world: ServerLevel, tethering: Tethering, pokemon: Pokemon) {
val now = world.gameTime
if (pokemon.isFainted() && !tethering.healingAfterFaint) {
tethering.beginRecovery(now, fainted = true)
syncRecovery(tethering)
}
val entity = (pokemon.entity ?: tethering.entityUuid?.let(world::getEntity) as? PokemonEntity)
?.takeIf { !it.isRemoved && it.tethering?.tetheringId == tethering.tetheringId }
if (tethering.conflictEnabled == null && entity != null) {
tethering.conflictEnabled = entity.getBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT)
}
if (entity != null && pokemon.isFainted()) entity.discard()
if (entity != null && !entity.isRemoved) {
if (tethering.conflictEnabled != null && entity.getBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT) != tethering.conflictEnabled) {
entity.setBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT, tethering.conflictEnabled == true)
entity.remakeBrain()
}
tethering.entityUuid = entity.uuid
tethering.lastEntityPos = entity.blockPosition()
entity.tethering = tethering
if (tethering.respawnAt != 0L || tethering.healingAfterFaint) {
tethering.respawnAt = 0L
tethering.healingAfterFaint = false
syncRecovery(tethering)
}
return
}
// A Pokémon in an unloaded chunk is still deployed. Never create its replacement.
val lastPosition = tethering.lastEntityPos
if (lastPosition != null) {
if (!world.hasChunkAt(lastPosition)) return
}
// The last saved position may predate a chunk crossing. Require the entire range
// to be entity-ticking before deciding that its missing Pokémon has disappeared.
for (chunkX in (minRoamPos.x shr 4)..(maxRoamPos.x shr 4)) {
for (chunkZ in (minRoamPos.z shr 4)..(maxRoamPos.z shr 4)) {
if (!world.isPositionEntityTicking(BlockPos(chunkX shl 4, blockPos.y, chunkZ shl 4))) return
}
}
if (tethering.respawnAt == 0L) {
tethering.beginRecovery(now, fainted = false)
syncRecovery(tethering)
return
}
if (now < tethering.respawnAt) return
if (tethering.healingAfterFaint) {
pokemon.heal()
if (pokemon.isFainted()) return
tethering.healingAfterFaint = false
syncRecovery(tethering)
}
val radius = Cobblemon.config.pastureMaxWanderDistance.toDouble()
val nearby = world.getEntitiesOfClass(PokemonEntity::class.java, AABB.ofSize(blockPos.toVec3d(), radius * 2, world.height.toDouble(), radius * 2)).size
val chunkDiameter = (radius / 16) * 2
if (nearby >= Cobblemon.config.pastureMaxPerChunk * chunkDiameter * chunkDiameter ||
!spawnPokemon(pokemon, tethering, blockState.getValue(HorizontalDirectionalBlock.FACING))) {
tethering.respawnAt = now + MISSING_ENTITY_COOLDOWN
syncRecovery(tethering)
}
}
private fun syncRecovery(tethering: Tethering) {
val world = level as? ServerLevel ?: return
val packet = UpdatePastureRecoveryPacket(tethering.pokemonId, tethering.healingAfterFaint, tethering.respawnAt)
world.server.playerList.players.filter(::isPlayerViewing).forEach { it.sendPacket(packet) }
}
fun setConflict(tethering: Tethering, enabled: Boolean) {
tethering.conflictEnabled = enabled
tethering.getPokemon()?.entity?.takeIf { it.tethering?.tetheringId == tethering.tetheringId }?.let {
it.setBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT, enabled)
it.remakeBrain()
}
setChanged()
val world = level as? ServerLevel ?: return
val packet = UpdatePastureConflictFlagPacket(tethering.pokemonId, enabled)
world.server.playerList.players.filter(::isPlayerViewing).forEach { it.sendPacket(packet) }
}
fun onBroken() {
if (level is ServerLevel) {
tetheredPokemon.toList().forEach { releasePokemon(it.pokemonId) }
@@ -451,10 +312,7 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
fun releasePokemon(pokemonId: UUID) {
val tethering = tetheredPokemon.find { it.pokemonId == pokemonId } ?: return
tethering.getPokemon()?.let { pokemon ->
pokemon.tetheringId = null
pokemon.onChange()
}
tethering.getPokemon()?.tetheringId = null
tetheredPokemon.remove(tethering)
setChanged()
}
@@ -462,10 +320,7 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
fun releaseAllPokemon(playerId: UUID): List<UUID> {
val unpastured = mutableListOf<UUID>()
tetheredPokemon.filter { it.playerId == playerId }.forEach {
it.getPokemon()?.let { pokemon ->
pokemon.tetheringId = null
pokemon.onChange()
}
it.getPokemon()?.tetheringId = null
tetheredPokemon.remove(it)
unpastured.add(it.pokemonId)
}
@@ -488,7 +343,9 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
private fun isPlayerViewing(player: ServerPlayer): Boolean {
val pastureLink = PastureLinkManager.getLinkByPlayer(player)
return pastureLink != null && pastureLink.pos == blockPos && pastureLink.dimension == player.level().dimension().location()
return pastureLink != null && pastureLink.pos == blockPos && pastureLink.dimension == ResourceLocation.tryParse(
player.level().dimensionTypeRegistration().registeredName // todo (techdaan): confirm this is good
)
}
override fun loadAdditional(nbt: CompoundTag, registryLookup: HolderLookup.Provider) {
@@ -496,9 +353,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
val list = nbt.getList(DataKeys.TETHER_POKEMON, CompoundTag.TAG_COMPOUND.toInt())
this.ownerId = if (nbt.hasUUID(DataKeys.TETHER_OWNER_ID)) nbt.getUUID(DataKeys.TETHER_OWNER_ID) else null
this.ownerName = nbt.getString(DataKeys.TETHER_OWNER_NAME).takeIf { it.isNotEmpty() } ?: ""
this.minRoamPos = NbtUtils.readBlockPos(nbt, DataKeys.TETHER_MIN_ROAM_POS).orElse(minRoamPos)
this.maxRoamPos = NbtUtils.readBlockPos(nbt, DataKeys.TETHER_MAX_ROAM_POS).orElse(maxRoamPos)
tetheredPokemon.clear()
for (tetheringNBT in list) {
tetheringNBT as CompoundTag
val tetheringId = tetheringNBT.getUUID(DataKeys.TETHERING_ID)
@@ -511,20 +365,17 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
minRoamPos = minRoamPos,
maxRoamPos = maxRoamPos,
playerId = playerId,
playerName = tetheringNBT.getString("PlayerName").ifEmpty { ownerName },
playerName = ownerName,
tetheringId = tetheringId,
pokemonId = pokemonId,
pcId = pcId,
entityId = entityId,
pasturePos = blockPos,
entityUuid = if (tetheringNBT.hasUUID("EntityUUID")) tetheringNBT.getUUID("EntityUUID") else null,
lastEntityPos = NbtUtils.readBlockPos(tetheringNBT, "LastEntityPos").orElse(null),
respawnAt = tetheringNBT.getLong("RespawnAt"),
healingAfterFaint = tetheringNBT.getBoolean("HealingAfterFaint"),
conflictEnabled = if (tetheringNBT.contains("PastureConflict")) tetheringNBT.getBoolean("PastureConflict") else null
pasturePos = blockPos
)
)
}
this.minRoamPos = NbtUtils.readBlockPos(nbt, DataKeys.TETHER_MIN_ROAM_POS).get()
this.maxRoamPos = NbtUtils.readBlockPos(nbt, DataKeys.TETHER_MAX_ROAM_POS).get()
}
override fun saveAdditional(nbt: CompoundTag, registryLookup: HolderLookup.Provider) {
@@ -537,12 +388,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
tetheringNBT.putUUID(DataKeys.POKEMON_UUID, tethering.pokemonId)
tetheringNBT.putUUID(DataKeys.PC_ID, tethering.pcId)
tetheringNBT.putInt(DataKeys.TETHERING_ENTITY_ID, tethering.entityId)
tetheringNBT.putString("PlayerName", tethering.playerName)
tethering.entityUuid?.let { tetheringNBT.putUUID("EntityUUID", it) }
tethering.lastEntityPos?.let { tetheringNBT.put("LastEntityPos", NbtUtils.writeBlockPos(it)) }
tetheringNBT.putLong("RespawnAt", tethering.respawnAt)
tetheringNBT.putBoolean("HealingAfterFaint", tethering.healingAfterFaint)
tethering.conflictEnabled?.let { tetheringNBT.putBoolean("PastureConflict", it) }
list.add(tetheringNBT)
}
nbt.put(DataKeys.TETHER_POKEMON, list)
@@ -551,4 +396,4 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
ownerId?.let { nbt.putUUID(DataKeys.TETHER_OWNER_ID, it) }
nbt.putString(DataKeys.TETHER_OWNER_NAME, this.ownerName)
}
}
}
@@ -11,8 +11,6 @@ package com.cobblemon.mod.common.client.gui.pasture
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.pasture.PasturePermissions
import com.cobblemon.mod.common.api.pasture.PastureRange
import net.minecraft.core.Direction
import com.cobblemon.mod.common.api.reactive.SettableObservable
import com.cobblemon.mod.common.client.gui.pc.PCGUIConfiguration
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
@@ -23,9 +21,7 @@ class PasturePCGUIConfiguration(
val pastureId: UUID,
val limit: Int,
val pasturedPokemon: SettableObservable<List<OpenPasturePacket.PasturePokemonDataDTO>>,
var permissions: PasturePermissions,
var range: PastureRange,
val facing: Direction
var permissions: PasturePermissions
) : PCGUIConfiguration(
exitFunction = { it.closeNormally(unlink = true) },
showParty = false,
@@ -36,6 +32,4 @@ class PasturePCGUIConfiguration(
}
},
canSelect = { pokemon -> !pokemon.isFainted() && pokemon.tetheringId == null }
) {
var editingRange = false
}
)
@@ -58,7 +58,6 @@ class PasturePokemonScrollList(
private val scrollOverlayResource = cobblemonResource("textures/gui/pasture/pasture_scroll_overlay.png")
private val slotResource = cobblemonResource("textures/gui/pasture/pasture_slot.png")
private val slotOwnerResource = cobblemonResource("textures/gui/pasture/pasture_slot_owner.png")
private val slotFaintedResource = cobblemonResource("textures/gui/pasture/pasture_slot_fainted.png")
}
private var scrolling = false
@@ -195,7 +194,7 @@ class PasturePokemonScrollList(
}
)
override fun getNarration() = if (pokemon.healingAfterFaint) lang("ui.pasture.fainted").append(" ").append(pokemon.displayName) else pokemon.displayName
override fun getNarration() = pokemon.displayName
override fun render(
context: GuiGraphics,
@@ -215,7 +214,7 @@ class PasturePokemonScrollList(
val matrixStack = context.pose()
blitk(
matrixStack = matrixStack,
texture = if (pokemon.healingAfterFaint) slotFaintedResource else if (isOwned()) slotOwnerResource else slotResource,
texture = if (isOwned()) slotOwnerResource else slotResource,
x = x,
y = y,
height = SLOT_HEIGHT,
@@ -235,8 +234,7 @@ class PasturePokemonScrollList(
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(13F, 35F, 0F)),
state = state,
partialTicks = partialTicks,
scale = 4.5F,
a = if (pokemon.healingAfterFaint) 0.7F else 1F
scale = 4.5F
)
matrixStack.popPose()
@@ -251,21 +249,14 @@ class PasturePokemonScrollList(
)
}
val recovering = pokemon.healingAfterFaint || pokemon.respawnAt > 0L
if (recovering) {
if (!pokemon.healingAfterFaint) {
drawScaledText(context, text = lang("ui.pasture.returning"),
x = x + 18, y = y + 7, scale = SCALE, colour = 0xFFFF8585.toInt(), shadow = true)
}
val remainingTicks = (pokemon.respawnAt - (client.level?.gameTime ?: 0L)).coerceAtLeast(0L)
val seconds = (remainingTicks + 19L) / 20L
val timer = if (remainingTicks == 0L) lang("ui.pasture.ready") else "%d:%02d".format(seconds / 60L, seconds % 60L).text()
drawScaledTextJustifiedRight(context = context, text = timer, x = x + 59, y = y + 17,
shadow = true, scale = SCALE)
} else {
drawScaledTextJustifiedRight(context = context, text = lang("ui.lv.number", pokemon.level),
x = x + 59, y = y + 17, shadow = true, scale = SCALE)
}
drawScaledTextJustifiedRight(
context = context,
text = lang("ui.lv.number", pokemon.level),
x = x + 59,
y = y + 17,
shadow = true,
scale = SCALE
)
drawScaledText(
context = context,
@@ -288,7 +279,7 @@ class PasturePokemonScrollList(
}
if (canUnpasture()) {
if (isOwned() && canDefend() == true) {
if (canDefend() == true) {
conflictButton.setPos(x + 44, y + 3)
conflictButton.render(context, mouseX, mouseY, partialTicks)
}
@@ -300,7 +291,7 @@ class PasturePokemonScrollList(
override fun mouseClicked(mouseX: Double, mouseY: Double, delta: Int): Boolean {
if (canUnpasture()) {
if (isOwned() && canDefend() == true && conflictButton.isHovered(mouseX, mouseY)) {
if (canDefend() == true && conflictButton.isHovered(mouseX, mouseY)) {
conflictButton.onPress()
return true
}
@@ -312,4 +303,4 @@ class PasturePokemonScrollList(
return false
}
}
}
}
@@ -1,225 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.gui.pasture
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.font
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.pc.StorageWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
import com.cobblemon.mod.common.net.messages.server.pasture.AdjustPastureRangePacket
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.core.Direction
import net.minecraft.network.chat.Component
class PastureRangeWidget(x: Int, y: Int, private val configuration: PasturePCGUIConfiguration) :
SoundlessWidget(x, y, StorageWidget.SCREEN_WIDTH, StorageWidget.SCREEN_HEIGHT, lang("ui.pasture.range")) {
private val rangeResource = cobblemonResource("textures/gui/pasture/pasture_range.png")
private val glowResource = cobblemonResource("textures/gui/pc/wallpaper/basic/glow/wallpaper_basic_05.png")
private val overlayResource = cobblemonResource("textures/gui/pc/pc_screen_overlay.png")
private val infoResource = cobblemonResource("textures/gui/pasture/pasture_range_help.png")
private val infoButtonResource = cobblemonResource("textures/gui/pasture/pasture_button.png")
private val infoButtonSize = 17
private val directions = listOf(configuration.facing, configuration.facing.clockWise, configuration.facing.opposite, configuration.facing.counterClockWise)
private val arrowBounds = listOf(
intArrayOf(75, 17, 103, 46), intArrayOf(116, 64, 152, 96),
intArrayOf(75, 109, 103, 143), intArrayOf(26, 64, 62, 96)
)
// Centers of the numeral shadows in pasture_range.png, relative to its (85, 27) panel origin.
private val numberPositions = listOf(89 to 37, 125 to 77, 89 to 114, 53 to 77)
private var hoveredDirection: Direction? = null
private var showInfo = false
val isInfoOpen get() = showInfo
fun closeInfo() { showInfo = false }
private val infoButtonX get() = x + 5
private val infoButtonY get() = y + 5
private val infoPanelX get() = x + 7
private val infoPanelY get() = y + 40
private val infoPanelWidth = 160
private val infoPanelHeight = 74
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
blitk(
matrixStack = context.pose(), texture = PCBoxWallpaperRepository.defaultWallpaper,
x = x, y = y, width = width, height = height
)
blitk(
matrixStack = context.pose(), texture = rangeResource,
x = x + 3, y = y + 3, width = width - 6, height = height - 6,
uOffset = 88, vOffset = 30, textureWidth = 349, textureHeight = 205
)
blitk(
matrixStack = context.pose(), texture = glowResource,
x = x - 17, y = y - 17, width = 208, height = 189
)
blitk(matrixStack = context.pose(), texture = overlayResource, x = x, y = y, width = width, height = height)
hoveredDirection = if (showInfo) null else directionAt(mouseX.toDouble(), mouseY.toDouble())
directions.indexOf(hoveredDirection).takeIf { it >= 0 }?.let { index ->
renderArrowHighlight(context, index)
}
context.pose().pushPose()
context.pose().translate(-0.5F, 0F, 0F)
directions.forEachIndexed { index, direction ->
val (numberX, numberY) = numberPositions[index]
drawScaledText(context, text = Component.literal(configuration.range[direction].toString()),
x = x + numberX + 1, y = y + numberY - 7, centered = true,
colour = 0xFFFFFFFF.toInt())
}
context.pose().popPose()
if (showInfo) context.fill(x + 3, y + 3, x + width - 3, y + height - 3, 0xAA002730.toInt())
val infoHovered = isOverInfoButton(mouseX.toDouble(), mouseY.toDouble())
// Use the same button face and persistent open-state highlight as the gear.
blitk(matrixStack = context.pose(), texture = infoButtonResource,
x = infoButtonX, y = infoButtonY, width = 13, height = infoButtonSize,
textureWidth = 70, textureHeight = 34)
blitk(matrixStack = context.pose(), texture = infoButtonResource,
x = infoButtonX + 13, y = infoButtonY, width = 4, height = infoButtonSize,
uOffset = 66, textureWidth = 70, textureHeight = 34)
if (showInfo || infoHovered) context.fill(infoButtonX + 2, infoButtonY + 2,
infoButtonX + 16, infoButtonY + 15, 0x88FFFFFF.toInt())
blitk(matrixStack = context.pose(), texture = infoResource,
x = infoButtonX + 4.5F, y = infoButtonY + 3.5F, width = 8, height = 10)
if (showInfo) {
val options = Minecraft.getInstance().options
val boxX = infoPanelX
val boxY = infoPanelY
val boxWidth = infoPanelWidth
val boxHeight = infoPanelHeight
context.fill(boxX + 1, boxY, boxX + boxWidth - 1, boxY + boxHeight, 0x96FFFFFF.toInt())
context.fill(boxX, boxY + 1, boxX + boxWidth, boxY + boxHeight - 1, 0x96FFFFFF.toInt())
blitk(matrixStack = context.pose(), texture = PCBoxWallpaperRepository.defaultWallpaper,
x = boxX + 1, y = boxY + 1, width = boxWidth - 2, height = boxHeight - 2,
textureWidth = StorageWidget.SCREEN_WIDTH, textureHeight = StorageWidget.SCREEN_HEIGHT)
val increaseBinding = if (options.keyAttack.matchesMouse(0)) lang("ui.pasture.range.left_click")
else options.keyAttack.translatedKeyMessage.copy()
val decreaseBinding = if (options.keyUse.matchesMouse(1)) lang("ui.pasture.range.right_click")
else options.keyUse.translatedKeyMessage.copy()
val columns = listOf(
Triple(boxX + 43, lang("ui.pasture.range.increase").bold(), listOf(increaseBinding, lang("ui.pasture.range.scroll_up"))),
Triple(boxX + 117, lang("ui.pasture.range.decrease").bold(), listOf(decreaseBinding, lang("ui.pasture.range.scroll_down")))
)
val detailWidth = columns.flatMap { it.third }.maxOf {
Minecraft.getInstance().font.width(it.copy().font(CobblemonResources.DEFAULT_LARGE))
}
val detailScale = minOf(1F, 72F / detailWidth)
drawScaledText(context, font = CobblemonResources.DEFAULT_LARGE,
text = lang("ui.pasture.range.help_title").bold(), x = boxX + 80, y = boxY + 8,
centered = true, shadow = true)
context.fill(boxX + 8, boxY + 22, boxX + boxWidth - 8, boxY + 23, 0x96FFFFFF.toInt())
context.fill(boxX + 80, boxY + 27, boxX + 81, boxY + 66, 0x96FFFFFF.toInt())
columns.forEach { (centerX, title, details) ->
drawScaledText(context, font = CobblemonResources.DEFAULT_LARGE,
text = title, x = centerX, y = boxY + 29, centered = true, shadow = true)
details.forEachIndexed { index, line ->
drawScaledText(context, font = CobblemonResources.DEFAULT_LARGE,
text = line, x = centerX, y = boxY + 44 + index * 14,
scale = detailScale, centered = true, shadow = true)
}
}
}
}
private fun renderArrowHighlight(context: GuiGraphics, index: Int) {
fun fill(left: Int, top: Int, right: Int, bottom: Int) {
context.fill(x + left, y + top, x + right, y + bottom, 0x66FFFFFF)
}
// Trace the arrow faces in pasture_range.png; horizontal arrows have longer stems.
// Keep their offset drop shadows visible instead of brightening the surrounding background.
when (index) {
0 -> {
for (row in 0..14) {
val halfWidth = 3 + minOf(row, 11)
fill(89 - halfWidth, 17 + row, 89 + halfWidth, 18 + row)
}
fill(81, 32, 97, 41)
}
1, 3 -> {
for (row in 0..26) {
val tip = 141 + minOf(row, 11, 26 - row)
if (index == 1) fill(137, 64 + row, tip, 65 + row)
else fill(178 - tip, 64 + row, 41, 65 + row)
}
if (index == 1) fill(116, 72, 137, 83)
else fill(41, 72, 62, 83)
}
2 -> {
fill(81, 109, 97, 123)
for (row in 0..14) {
val halfWidth = 14 - maxOf(0, row - 3)
fill(89 - halfWidth, 123 + row, 89 + halfWidth, 124 + row)
}
}
}
}
private fun directionAt(mouseX: Double, mouseY: Double): Direction? {
val index = arrowBounds.indexOfFirst { (left, top, right, bottom) ->
mouseX >= x + left && mouseX < x + right &&
mouseY >= y + top && mouseY < y + bottom
}
return directions.getOrNull(index)
}
private fun adjust(direction: Direction, increase: Boolean): Boolean {
AdjustPastureRangePacket(configuration.pastureId, direction, increase).sendToServer()
return true
}
private fun isOverInfoButton(mouseX: Double, mouseY: Double) =
mouseX >= infoButtonX && mouseX < infoButtonX + infoButtonSize &&
mouseY >= infoButtonY && mouseY < infoButtonY + infoButtonSize
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
if (pButton == 0 && isOverInfoButton(pMouseX, pMouseY)) {
showInfo = !showInfo
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1F))
return true
}
if (showInfo) {
if (pMouseX < infoPanelX || pMouseX >= infoPanelX + infoPanelWidth ||
pMouseY < infoPanelY || pMouseY >= infoPanelY + infoPanelHeight) closeInfo()
return true
}
val direction = directionAt(pMouseX, pMouseY) ?: return false
val options = Minecraft.getInstance().options
return when {
options.keyAttack.matchesMouse(pButton) -> adjust(direction, true)
options.keyUse.matchesMouse(pButton) -> adjust(direction, false)
else -> false
}
}
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
if (showInfo) return true
val direction = directionAt(mouseX, mouseY) ?: return false
if (scrollY == 0.0) return false
return adjust(direction, scrollY > 0)
}
override fun keyPressed(pKeyCode: Int, pScanCode: Int, pModifiers: Int): Boolean {
if (showInfo) return !Minecraft.getInstance().options.keyInventory.matches(pKeyCode, pScanCode)
val direction = hoveredDirection ?: return false
val options = Minecraft.getInstance().options
return when {
options.keyAttack.matches(pKeyCode, pScanCode) -> adjust(direction, true)
options.keyUse.matches(pKeyCode, pScanCode) -> adjust(direction, false)
else -> false
}
}
}
@@ -20,9 +20,7 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonP
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.sounds.SoundManager
import net.minecraft.network.chat.Component
import net.minecraft.client.gui.components.Button
class PastureWidget(
val storageWidget: StorageWidget,
@@ -34,8 +32,6 @@ class PastureWidget(
companion object {
private val baseResource = cobblemonResource("textures/gui/pasture/pasture_panel.png")
private val buttonResource = cobblemonResource("textures/gui/pasture/pasture_button.png")
private val gearResource = cobblemonResource("textures/gui/pasture/pasture_range_gear.png")
}
private val recallButton = RecallButton(
@@ -46,14 +42,6 @@ class PastureWidget(
UnpastureAllPokemonPacket(pasturePCGUIConfiguration.pastureId).sendToServer()
}
private val rangeButton = object : Button(x + 6, y + 174, 27, 17, lang("ui.pasture.range"), {
storageWidget.pcGui.setPastureRangeEditing(!pasturePCGUIConfiguration.editingRange)
}, DEFAULT_NARRATION) {
override fun playDownSound(soundManager: SoundManager) {
storageWidget.pcGui.playSound(CobblemonSounds.PC_CLICK)
}
}
val pastureScrollList = PasturePokemonScrollList(
listX = x + 6,
listY = y + 31,
@@ -82,29 +70,11 @@ class PastureWidget(
pastureScrollList.render(context, mouseX, mouseY, delta)
recallButton.render(context, mouseX, mouseY, delta)
rangeButton.message = lang(if (pasturePCGUIConfiguration.editingRange) "ui.pasture.storage" else "ui.pasture.range")
val buttonX = rangeButton.x
val buttonY = rangeButton.y
val highlighted = pasturePCGUIConfiguration.editingRange || rangeButton.isMouseOver(mouseX.toDouble(), mouseY.toDouble())
blitk(matrixStack = context.pose(), texture = buttonResource, x = buttonX, y = buttonY,
width = 23, height = 17, textureWidth = 70, textureHeight = 34)
blitk(matrixStack = context.pose(), texture = buttonResource, x = buttonX + 23, y = buttonY,
width = 4, height = 17, uOffset = 66, textureWidth = 70, textureHeight = 34)
if (highlighted) context.fill(buttonX + 2, buttonY + 2, buttonX + 26, buttonY + 15, 0x88FFFFFF.toInt())
val gearSize = 11
val gearX = buttonX + (rangeButton.width - gearSize) / 2
val gearY = buttonY + (rangeButton.height - gearSize) / 2
if (highlighted) blitk(matrixStack = context.pose(), texture = gearResource,
x = gearX + 1, y = gearY, width = gearSize, height = gearSize,
red = 0.2F, green = 0.2F, blue = 0.2F)
blitk(matrixStack = context.pose(), texture = gearResource,
x = gearX, y = gearY, width = gearSize, height = gearSize)
}
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
if (rangeButton.mouseClicked(pMouseX, pMouseY, pButton)) return true
if (recallButton.isHovered(pMouseX, pMouseY)) recallButton.mouseClicked(pMouseX, pMouseY, pButton)
if (pastureScrollList.isHovered(pMouseX, pMouseY)) pastureScrollList.mouseClicked(pMouseX, pMouseY, pButton)
return super.mouseClicked(pMouseX, pMouseY, pButton)
}
}
}
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.resources.sounds.SimpleSoundInstance
@@ -64,6 +65,9 @@ class FilterWidget(
renderCursor(context, input)
if (iconHovered(mouseX, mouseY)) {
context.renderTooltip(Minecraft.getInstance().font, lang("ui.pc.filter.tooltip"), mouseX, mouseY)
}
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
@@ -77,4 +81,4 @@ class FilterWidget(
fun iconHovered(mouseX: Int, mouseY: Int): Boolean = mouseX >= (x - 9) && mouseY >= (y + 3)
&& mouseX <= ((x - 9) + (ICON_SIZE * SCALE)) && mouseY <= ((y + 3) + (ICON_SIZE * SCALE))
}
}
@@ -20,7 +20,6 @@ import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
import com.cobblemon.mod.common.client.gui.ExitButton
import com.cobblemon.mod.common.client.gui.pasture.PasturePCGUIConfiguration
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.summary.Summary
import com.cobblemon.mod.common.client.gui.summary.Summary.Companion.iconCosmeticItemResource
@@ -141,10 +140,7 @@ class PCGUI(
// Add Exit Button
this.addRenderableWidget(
ExitButton(pX = x + 320, pY = y + 186) {
if (storageWidget.editingPastureRange) {
setPastureRangeEditing(false)
playSound(CobblemonSounds.PC_CLICK)
} else if (::wallpaperWidget.isInitialized && wallpaperWidget.visible) {
if (::wallpaperWidget.isInitialized && wallpaperWidget.visible) {
wallpaperWidget.visible = false
configuration.showParty = true
for (button in optionButtons) button.highlighted = false
@@ -162,7 +158,7 @@ class PCGUI(
pX = x + 220,
pY = y + 16,
forward = true
) { if (!storageWidget.editingPastureRange) storageWidget.box += 1 }
) { storageWidget.box += 1 }
)
// Add Backwards Button
@@ -171,7 +167,7 @@ class PCGUI(
pX = x + 117,
pY = y + 16,
forward = false
) { if (!storageWidget.editingPastureRange) storageWidget.box -= 1 }
) { storageWidget.box -= 1 }
)
// Add Filter Widget
@@ -201,8 +197,6 @@ class PCGUI(
storageWidget = storageWidget
)
this.addRenderableWidget(boxNameWidget)
filterWidget.active = !storageWidget.editingPastureRange
boxNameWidget.active = !storageWidget.editingPastureRange
// Initialise box options if not pasture
if (storageWidget.pastureWidget == null) {
@@ -697,10 +691,6 @@ class PCGUI(
super.render(context, mouseX, mouseY, delta)
if (!storageWidget.editingPastureRange && filterWidget.iconHovered(mouseX, mouseY)) {
context.renderTooltip(Minecraft.getInstance().font, lang("ui.pc.filter.tooltip"), mouseX, mouseY)
}
// Item Tooltip
if (pokemon != null) {
val displayedItem = if (showCosmeticItem) pokemon.cosmeticItem else pokemon.heldItemNoCopy()
@@ -721,34 +711,17 @@ class PCGUI(
}
}
fun setPastureRangeEditing(editing: Boolean) {
val pasture = configuration as? PasturePCGUIConfiguration ?: return
pasture.editingRange = editing
if (!editing) storageWidget.pastureRangeWidget?.closeInfo()
filterWidget.active = !editing
boxNameWidget.active = !editing
focused = null
storageWidget.resetSelected()
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
val rangeWidget = storageWidget.pastureRangeWidget
if (storageWidget.editingPastureRange && rangeWidget?.isInfoOpen == true &&
children().none { it is ExitButton && it.isHovered(mouseX, mouseY) }) {
return rangeWidget.mouseClicked(mouseX, mouseY, button)
}
// Trigger child component function as they will need to check the entire screen click area
if (::boxNameWidget.isInitialized && !storageWidget.editingPastureRange) boxNameWidget.mouseClicked(mouseX, mouseY, button)
if (::boxNameWidget.isInitialized) boxNameWidget.mouseClicked(mouseX, mouseY, button)
return super.mouseClicked(mouseX, mouseY, button)
}
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double, verticalAmount: Double): Boolean {
if (storageWidget.editingPastureRange &&
storageWidget.pastureRangeWidget?.mouseScrolled(mouseX, mouseY, amount, verticalAmount) == true) return true
storageWidget.pastureWidget?.let { pasture ->
if (pasture.pastureScrollList.isHovered) pasture.pastureScrollList.mouseScrolled(mouseX, mouseY, amount, verticalAmount)
}
if (!storageWidget.editingPastureRange && storageWidget.isHovered && mouseX < (storageWidget.x + StorageWidget.SCREEN_WIDTH)) this.storageWidget.box -= verticalAmount.toInt()
if (storageWidget.isHovered && mouseX < (storageWidget.x + StorageWidget.SCREEN_WIDTH)) this.storageWidget.box -= verticalAmount.toInt()
if (::wallpaperWidget.isInitialized && wallpaperWidget.isHovered) wallpaperWidget.mouseScrolled(mouseX, mouseY, amount, verticalAmount)
val infoBoxX = ((width - BASE_WIDTH) / 2) + 9
@@ -771,11 +744,6 @@ class PCGUI(
}
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
if (storageWidget.editingPastureRange) {
if (keyCode != InputConstants.KEY_ESCAPE &&
storageWidget.pastureRangeWidget?.keyPressed(keyCode, scanCode, modifiers) == true) return true
if (keyCode == InputConstants.KEY_RIGHT || keyCode == InputConstants.KEY_LEFT) return true
}
val boxNameFocused = this::boxNameWidget.isInitialized && boxNameWidget.isFocused
val filterFocused = this::filterWidget.isInitialized && filterWidget.isFocused
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.pasture.PasturePCGUIConfiguration
import com.cobblemon.mod.common.client.gui.pasture.PastureWidget
import com.cobblemon.mod.common.client.gui.pasture.PastureRangeWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.gui.PCBoxWallpaperRepository
@@ -75,9 +74,6 @@ class StorageWidget(
private val releaseNoButton: ReleaseConfirmButton
var pastureWidget: PastureWidget? = null
val pastureRangeWidget = (pcGui.configuration as? PasturePCGUIConfiguration)?.let { PastureRangeWidget(x, y, it) }
val editingPastureRange: Boolean
get() = (pcGui.configuration as? PasturePCGUIConfiguration)?.editingRange == true
var displayConfirmRelease = false
var screenLoaded = false
@@ -222,11 +218,6 @@ class StorageWidget(
}
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
if (editingPastureRange) {
pastureRangeWidget?.render(context, mouseX, mouseY, delta)
pastureWidget?.render(context, mouseX, mouseY, delta)
return
}
val matrices = context.pose()
// Party Label
if (pcGui.configuration.showParty) {
@@ -349,10 +340,6 @@ class StorageWidget(
}
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
if (editingPastureRange) {
return pastureRangeWidget?.mouseClicked(pMouseX, pMouseY, pButton) == true ||
pastureWidget?.mouseClicked(pMouseX, pMouseY, pButton) == true
}
if (displayConfirmRelease) {
if (releaseYesButton.isHovered(pMouseX, pMouseY)) releaseYesButton.mouseClicked(pMouseX, pMouseY, pButton)
if (releaseNoButton.isHovered(pMouseX, pMouseY)) releaseNoButton.mouseClicked(pMouseX, pMouseY, pButton)
@@ -748,6 +748,7 @@ class PokedexGUI private constructor(
}
TAB_DROPS -> {
(tabInfoElement as DropsScrollingWidget).dropTable = form.drops
(tabInfoElement as DropsScrollingWidget).aspects = aspects.toSet()
(tabInfoElement as DropsScrollingWidget).setEntries()
}
TAB_MOVES -> {
@@ -10,6 +10,9 @@ package com.cobblemon.mod.common.client.gui.pokedex.widgets
import com.cobblemon.mod.common.api.drop.DropTable
import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.drop.LootTableDropEntry
import com.cobblemon.mod.common.api.pokemon.feature.AbstractChoiceSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.ScrollingWidget
@@ -17,17 +20,26 @@ import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.util.itemRegistry
import com.cobblemon.mod.common.util.lang
import java.text.DecimalFormat
import com.cobblemon.mod.common.util.server
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import net.minecraft.ChatFormatting
import net.minecraft.Util
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.core.registries.Registries
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
import net.minecraft.util.FastColor
import net.minecraft.util.Mth
import net.minecraft.world.item.ItemStack
import java.text.DecimalFormat
class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrollingWidget.DropWidgetEntry>(
width = PokedexGUIConstants.HALF_OVERLAY_WIDTH - 2,
@@ -38,6 +50,7 @@ class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrol
) {
var dropTable: DropTable = DropTable()
var aspects: Set<String> = emptySet()
companion object {
val df = DecimalFormat("#.##")
@@ -50,9 +63,157 @@ class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrol
override fun getX() = pX
override fun getY() = pY
private fun checkPokemonProperty(propertiesString: String): Boolean {
println("CHECK PROPERTY CALLED: $propertiesString")
val split = propertiesString.split("=", limit = 2)
if (split.size != 2) return true
val key = split[0]
val value = split[1]
val provider = SpeciesFeatures.getFeatures()
.filterIsInstance<AbstractChoiceSpeciesFeatureProvider<*>>()
.firstOrNull { key in it.keys }
?: return true
val feature = provider.fromString(value) ?: return false
if (!provider.isAspect) return true
val requiredAspect = provider.getAspect(feature)
return requiredAspect in aspects
}
private fun checkPokemonConditions(condition: JsonObject): Boolean {
val conditionType = condition["condition"].asString
if (conditionType == "cobblemon:pokemon_properties") {
return checkPokemonProperty(
condition["properties"].asString
)
}
if (conditionType == "minecraft:all_of") {
val terms = condition["terms"]?.asJsonArray ?: return true
return terms.all {
checkPokemonConditions(it.asJsonObject)
}
}
if (conditionType == "minecraft:any_of") {
val terms = condition["terms"]?.asJsonArray ?: return true
return terms.any {
checkPokemonConditions(it.asJsonObject)
}
}
if (conditionType == "minecraft:inverted") {
val term = condition["term"]?.asJsonObject ?: return true
return !checkPokemonConditions(term)
}
return true
}
fun setEntries() {
dropTable.entries.forEach {
if (it is ItemDropEntry) addEntry(DropWidgetEntry(it))
clearEntries()
dropTable.entries.forEach { it ->
if (it is ItemDropEntry) {
addEntry(DropWidgetEntry(it, mutableSetOf(it.item)))
} else if (it is LootTableDropEntry) { // LootTable doesn't expose pools, so we gotta do all this bullshit
val server = server() ?: return
val lootTableResource = ResourceLocation.fromNamespaceAndPath(
it.id.namespace,
"loot_table/${it.id.path}.json"
)
val resource = server.resourceManager
.getResource(lootTableResource)
.orElse(null)
?: return@forEach
val json = resource.openAsReader().use { reader ->
JsonParser.parseReader(reader).asJsonObject
}
json.getAsJsonArray("pools")?.forEach { poolElement ->
val pool = poolElement.asJsonObject
val entries = pool.getAsJsonArray("entries") ?: return@forEach
val validEntries = entries
.map { entryElement ->
entryElement.asJsonObject
}.filter { entry ->
val conditions = entry["conditions"]?.asJsonArray ?: JsonArray()
conditions.all { condition ->
val conditionJson = condition.asJsonObject
val conditionType = conditionJson["condition"].asString
conditionType != "cobblemon:biome" && checkPokemonConditions(conditionJson)
}
}
val totalWeight = validEntries.sumOf { entry ->
entry["weight"]?.asInt ?: 1
}
for (entry in validEntries) {
val dropEntry = ItemDropEntry()
val conditions = entry["conditions"]?.asJsonArray ?: JsonArray()
val functions = entry["functions"]?.asJsonArray ?: JsonArray()
val items = mutableSetOf<ResourceLocation>()
var tag: ResourceLocation? = null
if (validEntries.size > 1 && totalWeight > 0) {
val weight = entry["weight"]?.asInt ?: 1
dropEntry.percentage = weight.toFloat() / totalWeight.toFloat() * 100F
}
conditions.forEach { condition ->
val conditionJson = condition.asJsonObject
val conditionType = conditionJson["condition"].asString
if (conditionType == "minecraft:random_chance") {
val chance = conditionJson["chance"].asFloat * 100F
if (validEntries.size > 1) {
dropEntry.percentage *= chance / 100F
} else {
dropEntry.percentage = chance
}
}
}
functions.forEach { function ->
val functionObj = function.asJsonObject
if (functionObj["function"].asString == "set_count") {
val count = functionObj["count"].asJsonObject
val min = count["min"].asInt
val max = count["max"].asInt
dropEntry.quantityRange = IntRange(min, max)
}
}
if (entry["type"].asString == "minecraft:tag") {
val itemRegistry = Minecraft.getInstance()
.level!!
.registryAccess()
.lookupOrThrow(Registries.ITEM)
val tagKey = TagKey.create(Registries.ITEM, ResourceLocation.parse(entry["name"].asString))
tag = tagKey.location
val tagItems = itemRegistry.getOrThrow(tagKey)
.stream()
.map { holder ->
holder.unwrapKey().map {
it.location()
}.orElse(null)
}.toList().filterNotNull()
items.addAll(tagItems)
} else if (entry["type"].asString == "minecraft:item") {
items.add(ResourceLocation.parse(entry["name"].asString))
}
addEntry(DropWidgetEntry(dropEntry, items, tag))
}
}
}
}
}
@@ -90,7 +251,7 @@ class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrol
shadow = true
)
if (dropTable.entries.size == 0) {
if (dropTable.entries.isEmpty()) {
drawScaledText(
context = context,
text = lang("ui.pokedex.info.drops_empty"),
@@ -128,7 +289,7 @@ class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrol
return children()[index] as DropWidgetEntry
}
class DropWidgetEntry(val entry: ItemDropEntry): Slot<DropWidgetEntry>() {
class DropWidgetEntry(val entry: ItemDropEntry, val items: MutableSet<ResourceLocation>, val tag: ResourceLocation? = null): Slot<DropWidgetEntry>() {
override fun render(
context: GuiGraphics,
index: Int,
@@ -141,9 +302,14 @@ class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrol
hovered: Boolean,
tickDelta: Float
) {
if (items.isEmpty()) return
context.pose().pushPose()
context.pose().translate(0f, 0f, 100f)
val itemStack = Minecraft.getInstance().player?.level()?.itemRegistry?.get(entry.item)?.defaultInstance ?: ItemStack.EMPTY
val index = ((Util.getMillis() / 1000L) % items.size).toInt()
val itemLocation = items.elementAt(index)
val itemStack = Minecraft.getInstance().player?.level()?.itemRegistry?.get(itemLocation)?.defaultInstance ?: ItemStack.EMPTY
renderScaledGuiItemIcon(
itemStack = itemStack,
x = x.toDouble(),
@@ -151,28 +317,28 @@ class DropsScrollingWidget(val pX: Int, val pY: Int): ScrollingWidget<DropsScrol
matrixStack = context.pose(),
scale = PokedexGUIConstants.SCALE.toDouble()
)
context.pose().pushPose()
val min = entry.quantityRange?.min() ?: entry.quantity
val max = entry.quantityRange?.max() ?: entry.quantity
// var itemName: String = Component.translatable(itemStack.hoverName).string
// itemName = if (itemName.length > 24) {
// itemName.substring(0, 24 - 3) + "..."
// } else {
// itemName
// }
val displayName = if (tag == null) {
itemStack.hoverName.copy().withStyle(ChatFormatting.BOLD)
} else {
Component.translatable("tag.item.${tag.namespace}.${tag.path.replace('/', '.')}").withStyle(ChatFormatting.BOLD)
}
val displayText: MutableComponent = if (entry.quantityRange != null) {
lang(
"ui.pokedex.info.drops_display",
itemStack.hoverName.copy().withStyle(ChatFormatting.BOLD),
displayName,
lang("ui.pokedex.info.drops_range", min, max)
)
} else {
lang(
"ui.pokedex.info.drops_display",
itemStack.hoverName.copy().withStyle(ChatFormatting.BOLD),
displayName,
lang("ui.pokedex.info.drops_amount", entry.quantity)
)
}
@@ -23,8 +23,6 @@ object OpenPastureHandler : ClientNetworkPacketHandler<OpenPasturePacket> {
pastureId = packet.pastureId,
limit = packet.limit,
permissions = packet.permissions,
range = packet.range,
facing = packet.facing,
pasturedPokemon = SettableObservable(packet.tetheredPokemon)
)
@@ -1,26 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.pasture
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.gui.pasture.PasturePCGUIConfiguration
import com.cobblemon.mod.common.client.gui.pc.PCGUI
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureRangePacket
import net.minecraft.client.Minecraft
import net.minecraft.client.resources.sounds.SimpleSoundInstance
object UpdatePastureRangeHandler : ClientNetworkPacketHandler<UpdatePastureRangePacket> {
override fun handle(packet: UpdatePastureRangePacket, client: Minecraft) {
val configuration = (client.screen as? PCGUI)?.configuration as? PasturePCGUIConfiguration ?: return
if (configuration.pastureId != packet.pastureId) return
configuration.range = packet.range
client.soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.PC_CLICK, 1F))
}
}
@@ -1,24 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.net.pasture
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.gui.pc.PCGUI
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureRecoveryPacket
import net.minecraft.client.Minecraft
object UpdatePastureRecoveryHandler : ClientNetworkPacketHandler<UpdatePastureRecoveryPacket> {
override fun handle(packet: UpdatePastureRecoveryPacket, client: Minecraft) {
val slots = (client.screen as? PCGUI)?.storage?.pastureWidget?.pastureScrollList?.children() ?: return
slots.firstOrNull { it.pokemon.pokemonId == packet.pokemonId }?.pokemon?.apply {
healingAfterFaint = packet.fainted
respawnAt = packet.respawnAt
}
}
}
@@ -117,6 +117,7 @@ import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.component.DataComponents
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.NbtUtils
@@ -132,6 +133,7 @@ import net.minecraft.network.protocol.game.DebugPackets
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.network.syncher.EntityDataSerializers
import net.minecraft.network.syncher.SynchedEntityData
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerEntity
import net.minecraft.server.level.ServerLevel
@@ -166,12 +168,14 @@ import net.minecraft.world.item.Items
import net.minecraft.world.level.Level
import net.minecraft.world.level.LightLayer
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.HorizontalDirectionalBlock
import net.minecraft.world.level.block.SuspiciousEffectHolder
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.gameevent.GameEvent
import net.minecraft.world.level.material.EmptyFluid
import net.minecraft.world.level.material.FluidState
import net.minecraft.world.level.pathfinder.PathType
import net.minecraft.world.level.storage.loot.LootTable
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import java.util.*
@@ -241,6 +245,12 @@ open class PokemonEntity(
override val schedulingTracker = SchedulingTracker()
override fun getDefaultLootTable(): ResourceKey<LootTable?>? {
println(cobblemonResource("pokemon/${this.pokemon.species.resourceIdentifier.path}"))
// return ResourceKey.create(Registries.LOOT_TABLE, )
return super.getDefaultLootTable()
}
val form: FormData
get() = pokemon.form
val behaviour: FormPokemonBehaviour
@@ -303,7 +313,6 @@ open class PokemonEntity(
var drops: DropTable? = null
var tethering: PokemonPastureBlockEntity.Tethering? = null
private var nextPastureReturnAttempt = 0
// TODO review if we still want this
var queuedToDespawn = false
@@ -738,29 +747,34 @@ open class PokemonEntity(
// Check to see if the entity needs recalled or repositioned if pastured.
fun checkPastureTether() {
val currentTethering = tethering ?: return
val world = level() as? ServerLevel ?: return
if (ticksLived == 1 && world.hasChunkAt(currentTethering.pasturePos)) {
val pasture = world.getBlockEntity(currentTethering.pasturePos) as? PokemonPastureBlockEntity
pasture?.tetheredPokemon?.find { it.tetheringId == currentTethering.tetheringId }?.let { tethering = it }
}
if (tethering!!.canRoamTo(x, z) || !world.hasChunkAt(currentTethering.pasturePos)) return
navigation.stop()
(moveControl as? PokemonMoveControl)?.apply { stop(); stopBanking() }
brain.eraseMemory(MemoryModuleType.WALK_TARGET)
deltaMovement = Vec3.ZERO
if (ticksLived < nextPastureReturnAttempt) return
val pasture = world.getBlockEntity(currentTethering.pasturePos) as? PokemonPastureBlockEntity
val position = pasture?.findSpawnPosition(this, blockPosition())
if (position != null) {
teleportTo(position.x, position.y, position.z)
nextPastureReturnAttempt = 0
} else if (pasture == null) {
tethering = null
pokemon.recall()
return
} else {
nextPastureReturnAttempt = ticksLived + 20
// Teleport a pastured mon back to the pasture block if they are out of range
if (this.tethering != null && !this.tethering!!.box.contains(this.x, this.y, this.z)) {
// Gather the ideal position (behind the pastureBlock)
val pastureBlockPos = this.tethering!!.pasturePos
val state = this.level().getBlockState(pastureBlockPos)
// Check to ensure we are working with a pastureblock here and it hasn't been broken
if (state.block == CobblemonBlocks.PASTURE) {
val direction = state.getValue(HorizontalDirectionalBlock.FACING)
val width = this.boundingBox.xsize
val tpPos = pastureBlockPos.offset(direction.normal.multiply(ceil(width).toInt() + 1)).center
val heightAllowance = 4.0 // Allow spawning up to x blocks above the pastureBlock y level
// Attempt tp and recall if it fails
if (!this.randomTeleport(tpPos.x, tpPos.y + heightAllowance, tpPos.z, false)) {
// If the teleport was not successful then recall the mon
this.tethering = null
this.pokemon.recall()
} else {
// Stop any now invalid navigation post teleport
this.navigation.stop()
}
} else {
// If the block is destroyed or something else went wrong.
this.tethering = null
this.pokemon.recall()
}
}
}
@@ -1795,7 +1809,7 @@ open class PokemonEntity(
removalObservable.emit(reason)
this.brain.clearMemories()
if (reason.shouldDestroy() && pokemon.tetheringId != null && tethering == null) {
if (reason.shouldDestroy() && pokemon.tetheringId != null) {
pokemon.tetheringId = null
}
if (evolutionEntity != null) {
@@ -29,7 +29,6 @@ import net.minecraft.tags.FluidTags
import net.minecraft.util.Mth
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.ai.control.MoveControl
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.level.material.FluidState
import net.minecraft.world.level.pathfinder.PathType
import net.minecraft.world.phys.AABB
@@ -107,14 +106,7 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
if (banking) {
pokemonEntity.yRot += bankRightDegreesPerTick
val forward = bankForwardBlocksPerTick * mediumSpeed
val tethering = pokemonEntity.tethering
if (tethering?.canRoamTo(
pokemonEntity.x - Mth.sin(pokemonEntity.yRot.toRadians()) * forward,
pokemonEntity.z + Mth.cos(pokemonEntity.yRot.toRadians()) * forward
) != false) {
pokemonEntity.travel(Vec3(0.0, bankUpwardsBlocksPerTick.toDouble(), bankForwardBlocksPerTick.toDouble()).scale(mediumSpeed.toDouble()))
}
pokemonEntity.travel(Vec3(0.0, bankUpwardsBlocksPerTick.toDouble(), bankForwardBlocksPerTick.toDouble()).scale(mediumSpeed.toDouble()))
if (bankDurationTicks > 0) {
bankDurationTicks--
}
@@ -288,16 +280,6 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
}
}
}
val tethering = pokemonEntity.tethering
val motion = mob.deltaMovement
if (tethering?.canRoamTo(mob.x, mob.z) == true &&
!tethering.canRoamTo(mob.x + motion.x, mob.z + motion.z)) {
mob.navigation.stop()
pokemonEntity.brain.eraseMemory(MemoryModuleType.WALK_TARGET)
stop()
stopBanking()
mob.deltaMovement = Vec3(0.0, motion.y, 0.0)
}
}
/*
@@ -387,4 +369,4 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
strafeForwards = 0.0f
strafeRight = 0.0f
}
}
}
@@ -0,0 +1,36 @@
package com.cobblemon.mod.common.loot
import com.cobblemon.mod.common.loot.conditions.BiomeLootItemCondition
import com.cobblemon.mod.common.loot.conditions.PokemonPropertiesLootItemCondition
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
object CobblemonLootItemConditions :
PlatformRegistry<Registry<LootItemConditionType>, ResourceKey<Registry<LootItemConditionType>>, LootItemConditionType>() {
@JvmField
val POKEMON_PROPERTIES_CONDITION = create(
cobblemonResource("pokemon_properties"),
LootItemConditionType(PokemonPropertiesLootItemCondition.CODEC)
)
@JvmField
val BIOME_CONDITION = create(
cobblemonResource("biome"),
LootItemConditionType(BiomeLootItemCondition.CODEC)
)
fun touch() = Unit
override val registry: Registry<LootItemConditionType>
get() = BuiltInRegistries.LOOT_CONDITION_TYPE
override val resourceKey: ResourceKey<Registry<LootItemConditionType>>
get() = Registries.LOOT_CONDITION_TYPE
}
@@ -0,0 +1,38 @@
package com.cobblemon.mod.common.loot.conditions
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.conditional.makeCodecForRegistryLikeCondition
import com.cobblemon.mod.common.loot.CobblemonLootItemConditions
import com.cobblemon.mod.common.util.toBlockPos
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.registries.Registries
import net.minecraft.world.level.biome.Biome
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
class BiomeLootItemCondition(
val biome: RegistryLikeCondition<Biome>
) : LootItemCondition {
override fun getType(): LootItemConditionType {
return CobblemonLootItemConditions.BIOME_CONDITION
}
override fun test(t: LootContext): Boolean {
val temp = biome.fits(t.level.getBiome(t.getParam(LootContextParams.ORIGIN).toBlockPos()))
return temp
}
companion object {
private val BIOME_CODEC = makeCodecForRegistryLikeCondition("biome", Registries.BIOME)
val CODEC: MapCodec<BiomeLootItemCondition> = RecordCodecBuilder.mapCodec { instance ->
instance.group(
BIOME_CODEC.fieldOf("biome")
.forGetter(BiomeLootItemCondition::biome)
).apply(instance, ::BiomeLootItemCondition)
}
}
}
@@ -0,0 +1,33 @@
package com.cobblemon.mod.common.loot.conditions
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.loot.CobblemonLootItemConditions
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
class PokemonPropertiesLootItemCondition(
val properties: PokemonProperties
) : LootItemCondition {
override fun getType(): LootItemConditionType {
return CobblemonLootItemConditions.POKEMON_PROPERTIES_CONDITION
}
override fun test(t: LootContext): Boolean {
val pokemon = t.getParamOrNull(LootContextParams.THIS_ENTITY) as? PokemonEntity ?: return false
return properties.matches(pokemon)
}
companion object {
val CODEC: MapCodec<PokemonPropertiesLootItemCondition> = RecordCodecBuilder.mapCodec { instance ->
instance.group(
PokemonProperties.CODEC.fieldOf("properties")
.forGetter(PokemonPropertiesLootItemCondition::properties)
).apply(instance, ::PokemonPropertiesLootItemCondition)
}
}
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.net.messages.client.pasture
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.pasture.PasturePermissions
import com.cobblemon.mod.common.api.pasture.PastureRange
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.net.IntSize
@@ -20,7 +19,6 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.core.Direction
/**
* Opens a pasture GUI using the provided data.
@@ -30,7 +28,7 @@ import net.minecraft.core.Direction
* @author Hiroku
* @since April 9th, 2023
*/
class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val tetheredPokemon: List<PasturePokemonDataDTO>, val permissions: PasturePermissions, val range: PastureRange, val facing: Direction) : NetworkPacket<OpenPasturePacket> {
class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val tetheredPokemon: List<PasturePokemonDataDTO>, val permissions: PasturePermissions) : NetworkPacket<OpenPasturePacket> {
class PasturePokemonDataDTO(
val pokemonId: UUID,
val playerId: UUID,
@@ -41,9 +39,7 @@ class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val
val heldItem: ItemStack,
val level: Int,
val entityKnown: Boolean,
var behaviourFlags: Set<PokemonBehaviourFlag> = emptySet(),
var healingAfterFaint: Boolean = false,
var respawnAt: Long = 0L
var behaviourFlags: Set<PokemonBehaviourFlag> = emptySet()
) {
companion object {
fun decode(buffer: RegistryFriendlyByteBuf): PasturePokemonDataDTO {
@@ -57,8 +53,6 @@ class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val
val level = buffer.readSizedInt(IntSize.U_SHORT)
val entityKnown = buffer.readBoolean()
val behaviourFlags = buffer.readList { it.readEnumConstant(PokemonBehaviourFlag::class.java) }.toSet()
val healingAfterFaint = buffer.readBoolean()
val respawnAt = buffer.readLong()
return PasturePokemonDataDTO(
pokemonId = pokemonId,
@@ -70,9 +64,7 @@ class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val
heldItem = heldItem,
level = level,
entityKnown = entityKnown,
behaviourFlags = behaviourFlags,
healingAfterFaint = healingAfterFaint,
respawnAt = respawnAt
behaviourFlags = behaviourFlags
)
}
}
@@ -88,8 +80,6 @@ class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val
buffer.writeSizedInt(IntSize.U_SHORT, level)
buffer.writeBoolean(entityKnown)
buffer.writeCollection(behaviourFlags) { _, flag -> buffer.writeEnumConstant(flag) }
buffer.writeBoolean(healingAfterFaint)
buffer.writeLong(respawnAt)
}
}
@@ -105,7 +95,7 @@ class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val
dtos.add(PasturePokemonDataDTO.decode(buffer))
}
val permissions = PasturePermissions.decode(buffer)
return OpenPasturePacket(pcId, pastureId, limit, dtos, permissions, PastureRange.decode(buffer), buffer.readEnum(Direction::class.java))
return OpenPasturePacket(pcId, pastureId, limit, dtos, permissions)
}
}
@@ -120,7 +110,5 @@ class OpenPasturePacket(val pcId: UUID, val pastureId: UUID, val limit: Int, val
tethered.encode(buffer)
}
permissions.encode(buffer)
range.encode(buffer)
buffer.writeEnum(facing)
}
}
@@ -1,31 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.messages.client.pasture
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.pasture.PastureRange
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
import java.util.UUID
class UpdatePastureRangePacket(val pastureId: UUID, val range: PastureRange) : NetworkPacket<UpdatePastureRangePacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeUUID(pastureId)
range.encode(buffer)
}
companion object {
val ID = cobblemonResource("update_pasture_range")
fun decode(buffer: RegistryFriendlyByteBuf) = UpdatePastureRangePacket(
buffer.readUUID(), PastureRange.decode(buffer)
)
}
}
@@ -1,29 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.messages.client.pasture
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import java.util.UUID
import net.minecraft.network.RegistryFriendlyByteBuf
data class UpdatePastureRecoveryPacket(val pokemonId: UUID, val fainted: Boolean, val respawnAt: Long) : NetworkPacket<UpdatePastureRecoveryPacket> {
override val id = ID
companion object {
val ID = cobblemonResource("update_pasture_recovery")
fun decode(buffer: RegistryFriendlyByteBuf) = UpdatePastureRecoveryPacket(buffer.readUUID(), buffer.readBoolean(), buffer.readLong())
}
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeUUID(pokemonId)
buffer.writeBoolean(fainted)
buffer.writeLong(respawnAt)
}
}
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.messages.server.pasture
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.Direction
import net.minecraft.network.RegistryFriendlyByteBuf
import java.util.UUID
class AdjustPastureRangePacket(val pastureId: UUID, val direction: Direction, val increase: Boolean) : NetworkPacket<AdjustPastureRangePacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeUUID(pastureId)
buffer.writeEnum(direction)
buffer.writeBoolean(increase)
}
companion object {
val ID = cobblemonResource("adjust_pasture_range")
fun decode(buffer: RegistryFriendlyByteBuf) = AdjustPastureRangePacket(
buffer.readUUID(), buffer.readEnum(Direction::class.java), buffer.readBoolean()
)
}
}
@@ -1,39 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.net.serverhandling.pasture
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.api.pasture.PastureLinkManager
import com.cobblemon.mod.common.api.pasture.PastureRange
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureRangePacket
import com.cobblemon.mod.common.net.messages.server.pasture.AdjustPastureRangePacket
import net.minecraft.core.Direction
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
object AdjustPastureRangeHandler : ServerNetworkPacketHandler<AdjustPastureRangePacket> {
override fun handle(packet: AdjustPastureRangePacket, server: MinecraftServer, player: ServerPlayer) {
val link = PastureLinkManager.getLinkByPlayer(player) ?: return
if (link.linkId != packet.pastureId || packet.direction.axis == Direction.Axis.Y) return
val pasture = player.serverLevel().getBlockEntity(link.pos) as? PokemonPastureBlockEntity ?: return
val range = pasture.getRange().adjusted(packet.direction, if (packet.increase) 1 else -1)
if (!range.isValid(PastureRange.MAX_DISTANCE)) {
UpdatePastureRangePacket(link.linkId, pasture.getRange()).sendToPlayer(player)
return
}
pasture.setRange(range)
for (viewer in player.serverLevel().players()) {
val viewerLink = PastureLinkManager.getLinkByPlayer(viewer) ?: continue
if (viewerLink.pos == link.pos && viewerLink.dimension == link.dimension) {
UpdatePastureRangePacket(viewerLink.linkId, range).sendToPlayer(viewer)
}
}
}
}
@@ -9,18 +9,24 @@
package com.cobblemon.mod.common.net.serverhandling.pasture
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.api.pasture.PastureLinkManager
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.server.pasture.SetPastureConflictPacket
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
object SetPastureConflictHandler : ServerNetworkPacketHandler<SetPastureConflictPacket> {
override fun handle(packet: SetPastureConflictPacket, server: MinecraftServer, player: ServerPlayer) {
val link = PastureLinkManager.getLinkByPlayer(player) ?: return
val pasture = player.level().getBlockEntity(link.pos) as? PokemonPastureBlockEntity ?: return
val tethering = pasture.tetheredPokemon.firstOrNull { it.pokemonId == packet.pokemonId && it.playerId == player.uuid } ?: return
pasture.setConflict(tethering, packet.enabled)
val world = player.level()
val entity = world.getEntitiesOfClass(PokemonEntity::class.java, player.boundingBox.inflate(64.0))
.firstOrNull { it.pokemon.uuid == packet.pokemonId }
?: return
entity.setBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT, packet.enabled)
entity.remakeBrain()
// Send packet from the server to client GUI to update the toggle button
UpdatePastureConflictFlagPacket(packet.pokemonId, packet.enabled).sendToPlayer(player)
}
}
}
@@ -1307,18 +1307,6 @@
"cobblemon.ui.sort.discovered": "Sort by discovered status",
"cobblemon.ui.pasture": "Pasture",
"cobblemon.ui.pasture.recall_all": "Recall All",
"cobblemon.ui.pasture.range": "Range",
"cobblemon.ui.pasture.storage": "PC",
"cobblemon.ui.pasture.fainted": "Fainted",
"cobblemon.ui.pasture.returning": "Returning",
"cobblemon.ui.pasture.ready": "Waiting",
"cobblemon.ui.pasture.range.left_click": "Left click",
"cobblemon.ui.pasture.range.right_click": "Right click",
"cobblemon.ui.pasture.range.help_title": "Range controls",
"cobblemon.ui.pasture.range.increase": "Increase",
"cobblemon.ui.pasture.range.decrease": "Decrease",
"cobblemon.ui.pasture.range.scroll_up": "Scroll up",
"cobblemon.ui.pasture.range.scroll_down": "Scroll down",
"cobblemon.pasture.too_many_nearby": "There are too many Pokémon nearby.",
"cobblemon.ui.interact.give.item": "Change held item",
"cobblemon.ui.interact.give.cosmetic_item": "Change cosmetic item",
@@ -3683,6 +3671,12 @@
"tag.item.cobblemon.terrain_plants": "Terrain Plants",
"tag.item.cobblemon.tall_flowers": "Tall Flowers",
"tag.item.cobblemon.small_flowers": "Small Flowers",
"tag.item.cobblemon.drops.coral": "Any Coral",
"tag.item.cobblemon.drops.dead_coral": "Any Dead Coral",
"tag.item.cobblemon.drops.dyes": "Any Dye",
"tag.item.cobblemon.drops.ink_sacs": "Any Ink Sac",
"tag.item.cobblemon.drops.flowers": "Any Flower",
"tag.item.cobblemon.drops.apricorn_sprouts": "Any Apricorn Sprout",
"tag.worldgen.biome.cobblemon.evolution.regional.bergmite_hisuibiome": "Hisuian",
"tag.worldgen.biome.cobblemon.evolution.regional.bergmite_kalosbiome": "Kalosian",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 B

@@ -0,0 +1,112 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:snowball",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:sweet_berries",
"functions": [
{
"function": "set_count",
"count": {
"min": 2,
"max": 4
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:never_melt_ice",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:occa_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/abomasnow"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:ender_pearl",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:twisted_spoon",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:kasib_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/abra"
}
@@ -0,0 +1,84 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:razor_claw",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:life_orb",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:roseli_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/absol"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:shed_shell",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/accelgor"
}
@@ -0,0 +1,111 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:iron_nugget",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 3
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:iron_sword",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:dusk_stone",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:ability_shield",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aegislash"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 3
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:rocky_helmet",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aerodactyl"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:raw_iron",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 3
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:hard_stone",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:chople_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aggron"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:nanab_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:tag",
"name": "cobblemon:drops/apricorn_sprouts",
"expand": true,
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aipom"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:ender_pearl",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 3
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:twisted_spoon",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:kasib_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/alakazam"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:sugar",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:cake",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/alcremie"
}
@@ -0,0 +1,121 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:cod",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone_meal",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:deep_sea_scale",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/alomomola"
}
@@ -0,0 +1,122 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:white_wool",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:chicken",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:yache_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/altaria"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:never_melt_ice",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/amaura"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:nanab_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:tag",
"name": "cobblemon:drops/apricorn_sprouts",
"expand": true,
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/ambipom"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:red_mushroom",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:cheri_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/amoonguss"
}
@@ -0,0 +1,95 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:mutton",
"functions": [
{
"function": "set_count",
"count": {
"min": 2,
"max": 4
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:cheri_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/ampharos"
}
@@ -0,0 +1,58 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:muscle_band",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:payapa_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/annihilape"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:quick_claw",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/anorith"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:sweet_apple",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:yache_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/appletun"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:apple",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:yache_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/applin"
}
@@ -0,0 +1,84 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:mystic_water",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:shed_shell",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:wepear_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/araquanid"
}
@@ -0,0 +1,58 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:razor_fang",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:shed_shell",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arbok"
}
@@ -0,0 +1,84 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:big_root",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:grassy_seed",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:kebia_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arboliva"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:rawst_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arcanine"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:rawst_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arcanine_hisui"
}
@@ -0,0 +1,5 @@
{
"type": "minecraft:generic",
"pools": [],
"random_sequence": "cobblemon:pokemon/arceus"
}
@@ -0,0 +1,5 @@
{
"type": "minecraft:generic",
"pools": [],
"random_sequence": "cobblemon:pokemon/archaludon"
}
@@ -0,0 +1,33 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:feather",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/archen"
}
@@ -0,0 +1,33 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:feather",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 3
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/archeops"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:haban_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arctibax"
}
@@ -0,0 +1,96 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:cod",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arctovish"
}
@@ -0,0 +1,60 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:feather",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arctozolt"
}
@@ -0,0 +1,139 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:string",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:spider_eye",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:rotten_flesh",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:poison_barb",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:shed_shell",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/ariados"
}
@@ -0,0 +1,58 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:quick_claw",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:shed_shell",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/armaldo"
}
@@ -0,0 +1,163 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:charcoal_stick",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:auspicious_armor",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:rawst_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:charcoal",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:any_of",
"terms": [
{
"condition": "cobblemon:biome",
"biome": "#minecraft:is_nether"
}
]
}
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:blaze_rod",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:all_of",
"terms": [
{
"condition": "cobblemon:biome",
"biome": "#minecraft:is_nether"
}
]
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/armarouge"
}
@@ -0,0 +1,84 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:misty_seed",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:kebia_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:fairy_feather",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aromatisse"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:raw_iron",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:hard_stone",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:chople_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aron"
}
@@ -0,0 +1,95 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:salmon",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone_meal",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/arrokuda"
}
@@ -0,0 +1,123 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:feather",
"functions": [
{
"function": "set_count",
"count": {
"min": 2,
"max": 4
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:chicken",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:never_melt_ice",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/articuno"
}
@@ -0,0 +1,123 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:feather",
"functions": [
{
"function": "set_count",
"count": {
"min": 2,
"max": 4
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:chicken",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:twisted_spoon",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/articuno_galar"
}
@@ -0,0 +1,58 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:oran_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:fairy_feather",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/audino"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:never_melt_ice",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/aurorus"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:ice",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 3
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:never_melt_ice",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:aspear_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/avalugg"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:ice",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:never_melt_ice",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:babiri_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/avalugg_hisui"
}
@@ -0,0 +1,58 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:dragon_fang",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:haban_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/axew"
}
@@ -0,0 +1,5 @@
{
"type": "minecraft:generic",
"pools": [],
"random_sequence": "cobblemon:pokemon/azelf"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:kebia_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/azumarill"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:kebia_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/azurill"
}
@@ -0,0 +1,84 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:dragon_fang",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:dragon_scale",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:yache_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/bagon"
}
@@ -0,0 +1,85 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:clay_ball",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:light_clay",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:colbur_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/baltoy"
}
@@ -0,0 +1,58 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:phantom_membrane",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:spell_tag",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/banette"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:rindo_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/barbaracle"
}
@@ -0,0 +1,59 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:clay_ball",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:rindo_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.025
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/barboach"
}
@@ -0,0 +1,95 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:salmon",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone_meal",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/barraskewda"
}
@@ -0,0 +1,95 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:salmon",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone_meal",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/basculegion"
}
@@ -0,0 +1,121 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:salmon",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 1
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone_meal",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:deep_sea_tooth",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/basculin"
}
@@ -0,0 +1,33 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/bastiodon"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:haban_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.25
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/baxcalibur"
}
@@ -0,0 +1,32 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:miracle_seed",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.1
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/bayleef"
}
@@ -0,0 +1,122 @@
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:snowball",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:cod",
"functions": [
{
"function": "set_count",
"count": {
"min": 0,
"max": 2
}
},
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
},
{
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"flags": {
"is_on_fire": true
}
}
},
{
"condition": "minecraft:entity_properties",
"entity": "direct_attacker",
"predicate": {
"equipment": {
"mainhand": {
"predicates": {
"minecraft:enchantments": [
{
"enchantments": "#minecraft:smelts_loot"
}
]
}
}
}
}
}
]
}
],
"function": "minecraft:furnace_smelt"
}
]
}
]
},
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "cobblemon:aspear_berry",
"functions": [
{
"count": {
"type": "minecraft:uniform",
"max": 1,
"min": 0
},
"enchantment": "minecraft:looting",
"function": "minecraft:enchanted_count_increase"
}
],
"conditions": [
{
"condition": "minecraft:random_chance",
"chance": 0.05
}
]
}
]
}
],
"random_sequence": "cobblemon:pokemon/beartic"
}
Loaded 100 of 2221 files, more files were not shown because too many files have changed in this diff. Show more