2015-10-03 2 views
-4

Я пытаюсь отменить повреждение стрелы, если имя игрока находится в списке 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

Я голосующий, чтобы закрыть этот вопрос как не относящийся к теме, поскольку ему не хватает конкретной проблемы или ошибки и кратчайшего кода, необходимого для его воспроизведения./Ваш ответ в другом замке. – Unihedron

+0

Блестящий. Повезло тебе! Просто потому, что ваш ответ неверен, вы закрываете сообщение. StackOverflow так же плох, как говорят люди. –

+0

Он работает только с повреждением в ближнем бою, как описано в описании. Это просто не работает для повреждения стрелы. Как это непонятно? –

ответ

2

Причина, по которой игрок получает урон снаряда, несмотря на то, что он находится в списке noPVP, - это способ, которым вы бросаете объекты. Обратите внимание, что как, так и 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); 
     } 
    } 
} 

В исходном коде, если игрок стрелял из лука в другой игрок, ваш плагин пытался бросить стрелку (Damager лица) к игроку, что невозможно (класс Player не является подклассом класса Arrow), тем самым вызывая ClassCastException и вызывая свой иначе правильный код после того, как инструкция else-if не будет выполнена.

Вот ClassCastException, когда корова повреждена субъектом с исходным кодом: ClassCastException when damaging cow

Я добавил два заявления печати для целей отладки после заливки объектов. Обратите внимание, что эти утверждения никогда не достигаются (поэтому никогда не отображаются) в случае генерируемого ClassCastException, но отображаются, если оба объекта являются игроками, и никакое исключение не выбрасывается.

enter image description here

С фрагментом кодом я написал выше, если имя игрока в списке noPVP любого повреждение снаряда отменяется: enter image description here

Обратите внимание, что это отменяет повреждение всех снарядов, если поврежденный игрок находится в списке noPVP. Чтобы только отменить повреждение в случае стрелки, вы можете проверить, является ли объект damager экземпляром класса Arrow. Вы даже можете проверить, была ли стрелка снята игроком или сущностью, такой как скелет, с использованием arrow.getShooter(), после того как вы нанесли объект damager стрелке.

+0

Извините, но это была не причина:/К сожалению, не работает! Но спасибо за подробный ответ, я все еще многому научился. –

+0

Эй, я всегда проверяю код, который я отправляю, поэтому почти гарантированно работает. Я уверен, что это связано с тем, как вы реализовали фрагмент кода или что-то еще, что отсутствует в вашем плагине. Я бы хотел взглянуть на ваш обновленный код, если вы отредактируете исходный вопрос! –

+0

+1 для углубленного ответа. Однако научитесь публиковать только в реальных вопросах в следующий раз, вместо вопросов без конкретной воспроизводимой проблемы. – Unihedron

Смежные вопросы