射弹伤害未被取消

Projectile damage not being cancelled

如果玩家的名字在列表中,我正在尝试取消箭的伤害 noPVP

@EventHandler
public void playerDamagesWhenToggledOff(EntityDamageByEntityEvent e) {

    Player victim = (Player) e.getEntity();
    Player damager = (Player) e.getDamager();

    if (getter.noPVP.contains(victim.getName()) || getter.noPVP.contains(damager.getName())) {
        e.setCancelled(true);
    }
    else if (e.getCause() == DamageCause.PROJECTILE && getter.noPVP.contains(victim.getName()) || getter.noPVP.contains(damager.getName())) {
        e.setCancelled(true);
    }

}      

这似乎行不通,即使 if 语句没问题。

尽管玩家在 noPVP 列表中,但仍会受到射弹伤害的原因是您施放实体的方式。请注意 e.getEntity()e.getDamager() return 都是 Entity 对象而不是 Player 对象。通过始终转换这些变量,您告诉插件它们是 Player class 的实例,而不知道它们到底是什么类型的实体,这通常是错误的,因为损坏者和损坏的实体可能是其他的实体类型(箭、动物、生物等​​)。

要解决此问题,您可以使用 instanceof 关键字确保在调用事件的特定情况下,破坏者或受损实体确实是玩家的实例。以下是您应该可以使用的代码的更新版本:

@EventHandler
public void playerDamagesWhenToggledOff(EntityDamageByEntityEvent e) {
    if (e.getEntity() instanceof Player) { // If damaged entity is a player
        Player victim = (Player) e.getEntity(); // Cast
        if (e.getDamager() instanceof Player) { // If the damager is also a player
            Player damager = (Player) e.getDamager();
            // Check if either of them are in the list, if so -> cancel damage
            if (getter.noPVP.contains(victim.getName()) || getter.noPVP.contains(damager.getName())) {
                e.setCancelled(true);
            }
        // If the damager was not a player, we can check if it was a projectile using the damage cause
        // Still check whether damaged player is in noPVP list
        } else if (e.getCause() == EntityDamageEvent.DamageCause.PROJECTILE && getter.noPVP.contains(victim.getName())) {
            e.setCancelled(true);
        }
    }
}

在您的原始代码中,如果一个玩家向另一个玩家射箭,您的插件会尝试将箭(伤害实体)投向玩家,这是不可能的(Player class 不是 Arrow class) 的子 class,从而导致 ClassCastException 并导致 else-if 语句后的其他正确代码无法执行。

这是当牛被实体损坏时的 ClassCastException,您的原始代码:

我在转换实体后添加了两个用于调试的打印语句。请注意,在抛出 ClassCastException 的情况下永远不会到达(因此永远不会显示)这些语句,但如果两个实体恰好都是玩家并且没有抛出异常,则会显示这些语句。

使用我上面发布的代码片段,如果玩家的名字在 noPVP 列表中,则任何射弹伤害都会被取消:

请注意,如果受伤的玩家在 noPVP 列表中,这将取消所有射弹的伤害。如果只取消箭的伤害,你可以检查伤害实体是否是 Arrow class 的实例。一旦你将破坏者实体投射到箭上,你甚至可以使用arrow.getShooter()检查箭是由玩家还是由骷髅等实体射出的。