Merge branch 'fix/equip-one-not-whole' into 'main'

fix: equipping stackable items now equips one item of stack

See merge request cable-mc/cobblemon!2469
This commit is contained in:
Polymeta
2026-10-09 14:31:02 +00:00
3 changed files with 54 additions and 9 deletions
+1 -1
View File
@@ -169,7 +169,7 @@
- Fixed crashes for addon species with non-Cobblemon namespaces, in evolution, fishing bait and Pokédex lookups.
- Bees now grow Apricorns and the Galarica Nut Bush, which were in the bee growables tag but never handled, and correctly spend their nectar when they do
- Saccharine Leaves can now be bone mealed
- Fixed equipping a stack of items instead of one item of a stack
### Developer
- Evolution requirements can now set `pokedexIcon` and `pokedexTooltip` directly in their JSON to control how they're shown on the Pokédex's evolution tree, for example:
```json
@@ -19,14 +19,13 @@ import net.minecraft.world.level.Level
class WearableHatItem(override val name: String): CobblemonItem(Properties()), WearableItem {
override fun use(level: Level, player: Player, usedHand: InteractionHand): InteractionResultHolder<ItemStack> {
val itemStack = player.getItemInHand(usedHand)
val hitPokemon = player.traceFirstEntityCollision(
entityClass = PokemonEntity::class.java,
maxDistance = player.entityInteractionRange().toFloat()
)
// If the player is looking at a Pokémon within range, block the ability to swap the item onto their head
return if (player.isCrouching && hitPokemon != null && hitPokemon.isOwnedBy(player)) {
InteractionResultHolder.fail(itemStack)
} else this.swapWithEquipmentSlot(this, level, player, usedHand)
if (player.isCrouching && hitPokemon != null && hitPokemon.isOwnedBy(player)) return InteractionResultHolder.fail(player.getItemInHand(usedHand))
return this.swapStackWithEquipmentSlot(level, player, usedHand)
}
}
}
@@ -10,10 +10,18 @@ package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.resources.ResourceLocation
import net.minecraft.stats.Stats
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Equipable
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.enchantment.EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE
import net.minecraft.world.item.enchantment.EnchantmentHelper
import net.minecraft.world.level.Level
interface WearableItem: Equipable {
interface WearableItem : Equipable {
val name: String
companion object {
@@ -23,5 +31,43 @@ interface WearableItem: Equipable {
fun getModel3d(): ResourceLocation = cobblemonResource("${MODEL_PATH}/${this.name}")
fun getModel2d(): ResourceLocation = cobblemonResource(this.name)
override fun getEquipmentSlot(): EquipmentSlot { return EquipmentSlot.HEAD }
}
override fun getEquipmentSlot(): EquipmentSlot {
return EquipmentSlot.HEAD
}
/**
* Swap stack with equipment slot
* Copied from vanilla, modified to account for stackable items
* @see Equipable.swapWithEquipmentSlot
*
* @param item
* @param level
* @param player
* @param hand
* @return the interaction result holder
*/
fun swapStackWithEquipmentSlot(
level: Level,
player: Player,
hand: InteractionHand
): InteractionResultHolder<ItemStack> {
var itemStack = player.getItemInHand(hand)
val equipmentSlot = player.getEquipmentSlotForItem(itemStack)
if (!player.canUseSlot(equipmentSlot)) return InteractionResultHolder.pass(itemStack)
val slotStack = player.getItemBySlot(equipmentSlot)
if (!(!EnchantmentHelper.has(slotStack, PREVENT_ARMOR_CHANGE) || player.isCreative) || ItemStack.matches(itemStack, slotStack)) return InteractionResultHolder.fail(itemStack)
if (!level.isClientSide()) player.awardStat(Stats.ITEM_USED.get(itemStack.item))
val equipStack = itemStack.split(1)
when {
itemStack.isEmpty -> itemStack = slotStack.copyAndClear()
else -> player.addItem(slotStack.copyAndClear())
}
player.setItemSlot(equipmentSlot, equipStack)
return InteractionResultHolder.sidedSuccess(itemStack, level.isClientSide())
}
}