2015-07-02 2 views
-1

Вот мой код:Мой таймер не работает в моем цикле

@SuppressWarnings("deprecation") 
@EventHandler 
public void onPlayerInteractBlockSummonElemental(PlayerInteractEvent event) { 
    final Player player = event.getPlayer(); 
    if (player.getFoodLevel() > 10){ 
     if (player.getItemInHand().getType() == Material.BLAZE_POWDER){ 
      List<Block> targets = player.getLineOfSight((Set)null, 100); 
      final Creature blaze1 = (Creature) player.getWorld().spawnCreature(player.getLocation(), EntityType.BLAZE); 
      final Creature blaze2 = (Creature) player.getWorld().spawnCreature(player.getLocation(), EntityType.BLAZE); 
      for (Block target : targets){ 
       player.playEffect(target.getLocation(), Effect.SMOKE,5); 
       List<Entity> victims = (List<Entity>) target.getWorld().getNearbyEntities(target.getLocation(), 2, 2, 2); 
       for (Entity victim2 : victims){ 
        final LivingEntity victim = (LivingEntity) victim2; 
        if (victim != blaze1){ 
         if (victim != blaze2){ 
          if (victim != player){ 
           blaze1.setTarget(victim); 
           blaze2.setTarget(victim); 
           int count = 0; 
           while (count < 6) { 
            Bukkit.getServer().getScheduler().runTaskLater(MagictgCraft.that, new Runnable(){ 
             public void run(){ 
              blaze1.setTarget(victim); 
              blaze2.setTarget(victim); 
              if (blaze1.getTarget() == player){ 
               blaze1.damage(20); 
              } 
              if (blaze2.getTarget() == player){ 
               blaze2.damage(20); 
              } 
             } 
            },50); 
            count = count + 1; 
           } 
           blaze1.damage(20); 
           blaze2.damage(20); 
          } 
         } 
        } 
       } 

      } 
     int manaused = player.getFoodLevel(); 
     manaused = manaused - 10; 
     player.setFoodLevel(manaused); 
     } 
    } 

Я использую таймер, чтобы проверить, что полыхает атаковать ли игрок, который бросает их, и сбрасывает цель. Я не знаю почему, но ничего внутри моей петли не происходит. Иногда вспышки умирают мгновенно, иногда вспышки просто появляются, и это все, иногда это порождает вспышки и выдает ошибку, говоря «не может передать событие PlayerInteractEvent в Plugin v1.0». Я уверен, что это из-за моего использования runTaskLater; У меня есть это для работы раньше, но в цикле он ведет себя по-другому. Я не знаю, почему это происходит, может ли кто-нибудь увидеть что-то не так?

+2

О, похоже, это довольно футуристическая конструкция! Порекомендовал бы вам реорганизовать его или хотя бы скрыть сложность, разделив его на разные функции! –

+2

Не связано с проблемой, которую вы решаете, но вы должны попытаться уменьшить количество отступов в этом блоке кода. Вы можете отменить некоторые ваши утверждения if и вернуться раньше, чтобы избежать некоторых из них. Например, 'if (a> 10) {...}' может стать 'if (a <= 10) {return; } ' –

+0

работает, если вы удаляете .getServer() – loli

ответ

1

Класс BukkitRunnable очень полезен в ситуациях, когда вы хотите запланировать несколько более сложную задачу (гораздо проще, например, отменить задачу после того, как определенное действие было завершено, поскольку BukkitRunnable может отменить себя).

targetSelector для объектов пламени настроен на таргетинг на ближайшую человеческую сущность, поэтому нерестование вспышек рядом с игроком неизбежно приведет к тому, что они будут нацелены на игрока довольно скоро и будут убиты (при использовании вашего кода). Вместо того, чтобы убивать вспышки, когда они нацелены на игрока, вероятно, было бы лучше постоянно повторно устанавливать свою цель, чтобы они атаковали только указанный объект.

Более элегантным решением было бы создание пользовательских кликов, которые не имеют целевого селектора или, по крайней мере, модифицированной версии, чтобы они не постоянно пытались найти ближайшего игрока.

У меня есть код ниже с пояснениями, которые заставляют блейз атаковать ближайшую сущность, которую игрок видит в своей линии зрения на 10 секунд. Примечание. Все, от поиска ближайшего объекта в представлении игрока до реализации целевого выбора, может быть сделано множеством различных и, вероятно, лучших способов.

Вот класс BlazeTask с помощью метода Run():

public class BlazeTask extends BukkitRunnable { 

    int ticks = 0; //Tick counter to keep track of how long this task has been running 

    private Blaze[] blazes; //The blazes 
    private LivingEntity target; //The target 

    public BlazeTask(Location location, LivingEntity target, int amount) { //The location where the blazes will be spawned, the target and the amount of blazes you want to spawn 
     blazes = new Blaze[amount]; //Initialize the blaze array 
     for (int i = 0; i < blazes.length; i++) { //Spawn as many blazes as we specified at the location 
      //Also, shift the spawn location by up to a block (random) so that the blazes aren't clumped 
      blazes[i] = (Blaze) location.getWorld().spawnEntity(location.clone().add(Math.random() - Math.random(), Math.random() - Math.random(), Math.random() - Math.random()), EntityType.BLAZE); 
     } 
     this.target = target; //Set the target variable 
    } 

    public void run() { 
     if (++ticks > 20 * 10) { //If this task runs every tick, 200 ticks will equal approximately 10 seconds 
      cancelTask(); //Cancel the task if this task has been running for 10 seconds or more 
     } 
     if (!isValid(target)) { //If the target has died or is null, the blazes have completed their goal 
      cancelTask(); //Cancel the task (kill the blazes too) 
     } 

     int invalidAmount = 0; //Amount of blazes that are either null or dead 
     for (Blaze blaze : blazes) { 
      if (isValid(blaze)) { //If the blaze is still there 
       Entity currentTarget = blaze.getTarget(); //Get the target 
       if (currentTarget == null || !currentTarget.equals(target)) { //If the blaze doesn't have a target or the target is not the one we want 
        blaze.setTarget(target); //Re-set the target 
       } 
      } else { //If the blaze is dead or gone, increment the counter 
       invalidAmount++; 
      } 
     } 

     //If for some reason, all the blazes were killed within the 10 seconds, cancel this task 
     if (invalidAmount == blazes.length) { 
      this.cancel(); 
     } 
    } 

    //This method is used above 
    private void cancelTask() { //Cancel the task by killing all blazes and also cancelling the task itself 
     for (Blaze blaze : blazes) { 
      if (isValid(blaze)) { 
       blaze.damage(20); 
      } 
     } 
     this.cancel(); 
    } 

    //This method is also used in the above run() method 
    private boolean isValid(Entity entity) { //Returns true if an entity is not dead and not null 
     return entity != null && !entity.isDead(); 
    } 

} 

А вот как я использую класс BlazeTask, а также найти ближайший объект в видении игрока:

@SuppressWarnings("deprecation") 
@EventHandler 
public void onPlayerInteract(PlayerInteractEvent event) { 
    final Player player = event.getPlayer(); 
    if (player.getFoodLevel() < 11) { //This is the reverse of player.getFoodLevel() > 10 
     return; //If the food level is 10, 9, 8 etc., don't do anything 
    } 
    if (player.getItemInHand().getType() != Material.BLAZE_POWDER) { 
     return; //If the player is NOT holding blaze powder, don't do anything 
    } 

    List<Block> sight = player.getLineOfSight((Set) null, 100); //Get the blocks in sight 

    //Get closest entity code 
    for (Block block : sight) { 
     player.playEffect(block.getLocation(), Effect.SMOKE, 1); //Play the smoke effect 
     List<Entity> entities = (List<Entity>) block.getWorld().getNearbyEntities(block.getLocation(), 2, 2, 2); //Get entities near block 
     if (entities.isEmpty()) { //If there are no nearby entities, continue to the next block in sight 
      continue; 
     } 
     for (Entity entity : entities) { 
      if (!(entity instanceof LivingEntity)) { //If the nearby entity is not a LivingEntity, continue onto the next nearby entity 
       continue; 
      } 
      LivingEntity victim = (LivingEntity) entity; //The closest living entity 
      if (victim.equals(player)) { //If the entity is the player itself, continue onto the next nearby entity 
       continue; 
      } 
      BlazeTask task = new BlazeTask(player.getLocation().clone().add(0, 4, 0), victim, 2); //Initialize the task, the 2 at the end is the number of blazes 
      task.runTaskTimer(this, 0, 1); //Run the task with a 0 tick delay and a period of 1 tick (run every tick) 
      player.setFoodLevel(player.getFoodLevel() - 10); //Lower food level 
      return; //Return so that the loop is exited and we don't keep checking blocks/entities 
     } 
    } 
} 
Смежные вопросы