弹丸损坏未被取消

时间:2015-10-03 08:36:51

标签: java bukkit

如果玩家的名字在列表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声明没问题,这似乎也不起作用。

1 个答案:

答案 0 :(得分:2)

尽管在noPVP列表中,玩家获得射弹伤害的原因是你施放实体的方式。请注意,e.getEntity()e.getDamager()都返回Entity个对象,而不是Player个对象。通过始终转换这些变量,您可以告诉插件它们是Player类的实例而不知道它们实际是什么类型的实体,这通常是错误的,因为损坏者和受损实体可能是其他类型的实体(箭头,动物,小怪等)。

要解决此问题,您可以确保在某个事件被调用的情况下,使用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类不是子类Arrow类的ClassCastException因此导致Arrow并在else-if语句之后导致您的代码无法正确执行。

当母牛被具有原始代码的实体损坏时,这是ClassCastException:ClassCastException when damaging cow

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

enter image description here

根据我在上面发布的代码段,如果玩家的名字在noPVP列表中,则任何射弹伤害都会被取消:enter image description here

请注意,如果受损的玩家在noPVP列表中,这将取消所有射弹的伤害。要仅在箭头的情况下取消损坏,您可以检查损坏者实体是否是arrow.getShooter()类的实例。一旦您将损坏者实体投射到箭头上,您甚至可以使用echo json_encode($rowcount); 检查箭头是由玩家还是实体(如骨架)拍摄的。