Skip to content

Commit

Permalink
Fix custom tools not receiving damage on entity attack
Browse files Browse the repository at this point in the history
  • Loading branch information
NichtStudioCode committed Jan 20, 2025
1 parent 873caab commit acbca23
Showing 1 changed file with 51 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package xyz.xenondevs.nova.patch.impl.item

import net.minecraft.stats.Stats
import net.minecraft.tags.ItemTags
import net.minecraft.tags.TagKey
import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.BlockState
import org.bukkit.craftbukkit.block.CraftBlock
Expand All @@ -18,18 +22,18 @@ import xyz.xenondevs.nova.util.item.novaItem
import xyz.xenondevs.nova.util.item.takeUnlessEmpty
import xyz.xenondevs.nova.util.reflection.ReflectionRegistry
import xyz.xenondevs.nova.util.reflection.ReflectionUtils
import xyz.xenondevs.nova.world.item.behavior.Damageable
import xyz.xenondevs.nova.world.item.behavior.Tool
import net.minecraft.world.entity.player.Player as MojangPlayer
import net.minecraft.world.item.ItemStack as MojangStack

private val ITEM_STACK_IS_TAG = ReflectionUtils.getMethod(ItemStack::class, "is", TagKey::class)

@Suppress("unused")
internal object ToolPatches : MultiTransformer(CraftBlock::class, MojangPlayer::class) {
internal object ToolPatches : MultiTransformer(CraftBlock::class, Player::class, ItemStack::class) {

override fun transform() {
transformCraftBlockIsPreferredTool()
transformPlayerAttack()
transformItemStackHurtEnemy()
}

/**
Expand All @@ -46,15 +50,15 @@ internal object ToolPatches : MultiTransformer(CraftBlock::class, MojangPlayer::
}

@JvmStatic
fun isPreferredTool(block: CraftBlock, blockState: BlockState, tool: MojangStack): Boolean {
fun isPreferredTool(block: CraftBlock, blockState: BlockState, tool: ItemStack): Boolean {
return !blockState.requiresCorrectToolForDrops() || ToolUtils.isCorrectToolForDrops(block, tool.asBukkitMirror().takeUnlessEmpty())
}

/**
* Patches the Player#attack method to use properly perform sweep attacks.
*/
private fun transformPlayerAttack() {
VirtualClassPath[MojangPlayer::attack].replaceEvery(
VirtualClassPath[Player::attack].replaceEvery(
0, 1,
{ invokeStatic(::canDoSweepAttack) },
{
Expand All @@ -65,7 +69,7 @@ internal object ToolPatches : MultiTransformer(CraftBlock::class, MojangPlayer::
}

@JvmStatic
fun canDoSweepAttack(itemStack: MojangStack): Boolean {
fun canDoSweepAttack(itemStack: ItemStack): Boolean {
val novaItem = itemStack.novaItem

if (novaItem != null) {
Expand All @@ -75,4 +79,45 @@ internal object ToolPatches : MultiTransformer(CraftBlock::class, MojangPlayer::
}
}

/**
* Transforms ItemStack#hurtEnemy and ItemStack#postHurtEnemy to implement item damage on entity attack.
*/
private fun transformItemStackHurtEnemy() {
// hurtEnemy needs to return true, otherwise postHurtEnemy is not called
VirtualClassPath[ItemStack::hurtEnemy].delegateStatic(::hurtEnemy)
VirtualClassPath[ItemStack::postHurtEnemy].delegateStatic(::postHurtEnemy)
}

@JvmStatic
fun hurtEnemy(itemStack: ItemStack, enemy: LivingEntity, attacker: LivingEntity): Boolean {
val novaItem = itemStack.novaItem
val isWeapon = if (novaItem != null) {
val damageable = novaItem.getBehaviorOrNull<Damageable>()
?: return false
damageable.itemDamageOnAttackEntity > 0
} else {
itemStack.item.hurtEnemy(itemStack, enemy, attacker)
}

if (isWeapon && attacker is Player) {
attacker.awardStat(Stats.ITEM_USED.get(itemStack.item))
}

return isWeapon
}

@JvmStatic
fun postHurtEnemy(itemStack: ItemStack, enemy: LivingEntity, attacker: LivingEntity) {
val novaItem = itemStack.novaItem

val damage: Int
if (novaItem != null) {
val damageable = novaItem.getBehaviorOrNull<Damageable>() ?: return
damage = damageable.itemDamageOnAttackEntity
itemStack.hurtAndBreak(damage, attacker, EquipmentSlot.MAINHAND)
} else {
itemStack.item.postHurtEnemy(itemStack, enemy, attacker)
}
}

}

0 comments on commit acbca23

Please sign in to comment.