如果玩家的名字在列表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
声明没问题,这似乎也不起作用。
答案 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:
我在构建实体后添加了两个用于调试目的的print语句。请注意,在抛出ClassCastException的情况下,永远不会达到这些语句(因此从不显示),但如果两个实体碰巧都是玩家并且没有抛出异常,则会显示这些语句。
根据我在上面发布的代码段,如果玩家的名字在noPVP列表中,则任何射弹伤害都会被取消:
请注意,如果受损的玩家在noPVP列表中,这将取消所有射弹的伤害。要仅在箭头的情况下取消损坏,您可以检查损坏者实体是否是arrow.getShooter()
类的实例。一旦您将损坏者实体投射到箭头上,您甚至可以使用echo json_encode($rowcount);
检查箭头是由玩家还是实体(如骨架)拍摄的。