Остановка циклов Bukkit и запись в журнал, когда лошадь умирает в Bukkit

сегодня я пытался сделать плагин, который порождает лошадь-скелет, а частицы огня окружают лошадь. У меня есть эта часть, но всякий раз, когда кто-то убивает костяную лошадь, частицы огня остаются там. Кто-нибудь, пожалуйста, помогите?

Также мой код (2 класса):

package survivalcraft.FireHorse;
import java.util.logging.Logger;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.command.CommandSender;
import org.bukkit.command.Command;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse.Variant;
import org.bukkit.entity.Player;
import org.bukkit.entity.Horse;
import org.bukkit.inventory.HorseInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.Material;

public class Main extends JavaPlugin{
public static Main plugin;
public final Logger logger = Logger.getLogger("Minecraft");

@Override
public void onDisable(){
    PluginDescriptionFile pdf = this.getDescription();
    this.logger.info(pdf.getName() + " version " + pdf.getVersion() + " has been disabled! Neigh! ;D");
}

@Override
public void onEnable(){
    PluginDescriptionFile pdf = this.getDescription();
    this.logger.info(pdf.getName() + " version " + pdf.getVersion() + " has been enabled! Neigh! ;D");
}

@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
    Player player = (Player) sender;
    if(sender instanceof Player){
        if(player.hasPermission("firehorse.spawn")){
            if(commandLabel.equalsIgnoreCase("firehorse") || commandLabel.equalsIgnoreCase("fh")){
                if(args.length == 0){
                    Horse horse = (Horse) player.getWorld().spawnEntity(player.getLocation(), EntityType.HORSE);
                    HorseInventory horseinv = null;
                    ItemStack saddle = new ItemStack(Material.SADDLE);
                    horse.setVariant(Variant.SKELETON_HORSE);
                    horse.setCustomName(player.getDisplayName() + "'s Fire Horse");                     
                    horse.setTamed(true);
                    horseinv.setSaddle(saddle);
                    Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new HorseTimer(horse), 0l, 5l);
                }else{
                    player.sendMessage(ChatColor.RED + "Usage: /firehorse");
                }
            }
        }else{
            player.sendMessage(ChatColor.RED + "You can't spawn a fire horse!");
        }
    }else{
        player.sendMessage(ChatColor.RED + "You must be a player in order to spawn a fire horse!");
    }   
    return false;
}   
}

2-й класс:

package survivalcraft.FireHorse;

import org.bukkit.Effect;
import org.bukkit.entity.Horse;

public class HorseTimer implements Runnable{
private Horse horse;

public HorseTimer(Horse horse){
    this.horse = horse;
}

@Override
public void run(){
    horse.getWorld().playEffect(horse.getLocation(), Effect.MOBSPAWNER_FLAMES, 0);
}
}

person CODER6769    schedule 04.08.2014    source источник


Ответы (5)


1-й: проверьте, жива ли лошадь, как написал @Momo, с небольшой поправкой от @CrypticStorm.

2-е: класс HorseTimer должен расширять BukkitRunnable вместо реализации Rumnable, чтобы он мог отменить себя, см. http://wiki.bukkit.org/Scheduler_Programming#Self-Canceling_Example_2

person thekiwi5000    schedule 05.08.2014

Вы должны изменить scheduleSyncRepeatingTask на runTaskTimer, поскольку сейчас это правильный метод. Это возвращает int, представляющий его идентификатор, который вы можете сохранить, а затем вызвать Bukkit.getScheduler().cancelTask(int id), когда вы слушаете EntityDeathEvent.

person CrypticStorm    schedule 04.08.2014
comment
scheduleSyncRepeatingTask также возвращает целое число, которое можно использовать для задачи. - person William Reed; 04.08.2014
comment
В любом случае вам нужен идентификатор задачи. - person CrypticStorm; 04.08.2014
comment
А зачем предлагать менять? - person William Reed; 04.08.2014
comment
РЕДАКТИРОВАТЬ: ой, ошибочный контекст. Я предлагаю изменить его, потому что нерекомендуемые асинхронные методы больше не подпадают под одно и то же соглашение об именах. - person CrypticStorm; 04.08.2014

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

public class Main extends JavaPlugin{
public static Main plugin;
public final Logger logger = Logger.getLogger("Minecraft");

@Override
public void onDisable(){
    PluginDescriptionFile pdf = this.getDescription();
    this.logger.info(pdf.getName() + " version " + pdf.getVersion() + " has been disabled! Neigh! ;D");
    Bukkit.getServer().getPluginManager().registerEvents(this, this);
}

@Override
public void onEnable(){
    PluginDescriptionFile pdf = this.getDescription();
    this.logger.info(pdf.getName() + " version " + pdf.getVersion() + " has been enabled! Neigh! ;D");
}

Map<UUID, Integer> tasks = new HashMap<UUID, Integer>();
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
    Player player = (Player) sender;
    if(sender instanceof Player){
        if(player.hasPermission("firehorse.spawn")){
            if(commandLabel.equalsIgnoreCase("firehorse") || commandLabel.equalsIgnoreCase("fh")){
                if(args.length == 0){
                    Horse horse = (Horse) player.getWorld().spawnEntity(player.getLocation(), EntityType.HORSE);
                    HorseInventory horseinv = null;
                    ItemStack saddle = new ItemStack(Material.SADDLE);
                    horse.setVariant(Variant.SKELETON_HORSE);
                    horse.setCustomName(player.getDisplayName() + "'s Fire Horse");                     
                    horse.setTamed(true);
                    horseinv.setSaddle(saddle);
                    int id = Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new HorseTimer(horse), 0l, 5l);
                    tasks.put(horse.getUniqueId(), id);
                }else{
                    player.sendMessage(ChatColor.RED + "Usage: /firehorse");
                }
            }
        }else{
            player.sendMessage(ChatColor.RED + "You can't spawn a fire horse!");
        }
    }else{
        player.sendMessage(ChatColor.RED + "You must be a player in order to spawn a fire horse!");
    }   
    return false;
} 

    Map<UUID, Integer> map = null;
    @EventHandler
    public void handleDeaths(EntityDeathEvent event){
        for(UUID id : map.keySet())
            if(event.getEntity().getUniqueId().equals(id))
                Bukkit.getServer().getScheduler().cancelTask(map.get(id));
    }

}
person William Reed    schedule 04.08.2014
comment
Logger.getLogger("Minecraft"); не гарантируется будущими версиями Bukkit. Вы должны использовать Plugin.getLogger() для всех журналов, сделанных вашим плагином. - person CrypticStorm; 04.08.2014
comment
Я предполагаю, что это ^ для оператора, который сам не вел журнал, когда редактировал - person William Reed; 04.08.2014
comment
ошибся, да. Я довольно не в своей игре сегодня. Я думал, ты добавил это. - person CrypticStorm; 04.08.2014

Добавьте эту проверку в свой метод run():

if (!horse.isDead()) {
    // Spawn particles
}

Это предотвратит появление частиц на мертвой лошади.

person Momo    schedule 04.08.2014
comment
Во-первых, это метод isAlive(). Во-вторых, это не отменяет работоспособность (плохо). В-третьих, неотмененный runnable содержит ссылку на Entity, препятствующую сборке мусора. Это не способ правильно отменить runnable. - person CrypticStorm; 04.08.2014
comment
@CrypticStorm Я знаю, что этот вопрос старый, но на самом деле это хороший метод. Вы можете просто сделать: if (horse.isAlive()) // сделать еще что-нибудь this.cancel(); - person Bob; 21.12.2015

Все ответы делают свое дело, но неэффективно.

DeathEvent может быть оживленным местом, особенно с моб-фермами.

Вот лучшая альтернатива для добавления в ваш метод run():

if (horse.isAlive()) {
    // spawn particles
} else {
    this.cancel();
}
person Bob    schedule 21.12.2015