当HashMap值为true时,任务不会被取消

时间:2015-08-28 14:33:21

标签: java bukkit

我目前正在学习预定的任务。

基本上,我制作了一个Bukkit插件,您可以在其中启用或禁用PVP。 当玩家输入/ pvp on或/ pvp off时,他们不能移动5秒,但是,任务取消似乎不会执行。

主要课程:

package me.mortadelle2.pvptoggle;

import java.util.ArrayList;
import java.util.HashMap;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;

public class PVPToggle extends JavaPlugin {

    ArrayList<String> noPVP = new ArrayList<String>();

    HashMap<String, Boolean> hasMoved = new HashMap<String, Boolean>();

    Player p;

    public void onEnable() {

        new PlayerDamage(this);
        getLogger().info("PVPToggle toggled!");

    }

    public void onDisable() {

        getLogger().info("PVPToggle disabled!");

    }

    public boolean onCommand(CommandSender sender, Command cmd, String label,
            String[] args) {

        p = (Player) sender;

        if (cmd.getName().equalsIgnoreCase("pvp")) {

            if (args.length == 0) {

                p.sendMessage(ChatColor.RED + "Invalid usage! /pvp [on or off]");
                return true;

            }

            if (args.length == 1) {

                if (args[0].equalsIgnoreCase("on")) {

                    p.sendMessage(ChatColor.YELLOW
                            + "PVP will be turned on in 5 seconds! Don't move!");
                    hasMoved.remove(p.getName());
                    hasMoved.put(p.getName(), false);

                    int turnOn = this.getServer().getScheduler()
                            .scheduleSyncDelayedTask(this, new Runnable() {

                                @Override
                                public void run() {

                                    if (hasMoved.get(p.getName()) == false) {
                                        noPVP.remove(p.getName());
                                        p.sendMessage(ChatColor.YELLOW
                                                + "You have turned PVP on!");
                                    }

                                }
                            }, 100L);

                    if (hasMoved.get(p.getName()) == true) {
                        p.sendMessage(ChatColor.RED
                                + "You moved so the action was cancelled.");
                        this.getServer().getScheduler().cancelTask(turnOn);
                    }

                    return true;

                }

                if (args[0].equalsIgnoreCase("off")) {

                    p.sendMessage(ChatColor.YELLOW
                            + "PVP will be turned off in 5 seconds. Don't move!");

                    hasMoved.remove(p.getName());
                    hasMoved.put(p.getName(), false);

                    int turnOff = this.getServer().getScheduler()
                            .scheduleSyncDelayedTask(this, new Runnable() {

                                @Override
                                public void run() {

                                    if (hasMoved.get(p.getName()) == false) {
                                        noPVP.add(p.getName());
                                        p.sendMessage(ChatColor.YELLOW
                                                + "You have turned PVP off!");
                                    }

                                }

                            }, 100L);

                    if (hasMoved.get(p.getName()) == true) {
                        p.sendMessage(ChatColor.RED
                                + "You moved so the action was cancelled.");
                        this.getServer().getScheduler().cancelTask(turnOff);
                    }

                    return true;
                }

            }

        }

        return false;
    }

}

听众课程:

    package me.mortadelle2.pvptoggle;

import org.bukkit.Bukkit;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.util.Vector;

public class PlayerDamage implements Listener{

    PVPToggle getter;

    public PlayerDamage(PVPToggle plugin) {

        plugin.getServer().getPluginManager().registerEvents(this, plugin);

        this.getter = plugin;

    }

    @EventHandler
    public void playerJoins(PlayerJoinEvent e){

        Player p = e.getPlayer();
        getter.hasMoved.put(p.getName(), false);

    }

    @EventHandler
    public void playerDamages(EntityDamageByEntityEvent e){

        Player victim = (Player) e.getEntity();
        Player killer = (Player) e.getDamager();

        victim.sendMessage("hey");

        if (getter.noPVP.contains(victim.getName()) || getter.noPVP.contains(killer.getName())){
            e.setCancelled(true);
        }

    }

    @EventHandler
    public void playerShootsPlayer(EntityShootBowEvent e){

        Arrow a = (Arrow) e.getEntity();

        Player shooter = (Player) a.getShooter();

        if (getter.noPVP.contains(a.getName()) || getter.noPVP.contains(shooter.getName())){
            e.setCancelled(true);
        }



    }

    @EventHandler
    public void playerMoves(PlayerMoveEvent e) {

        final Player p = e.getPlayer();

        final Vector pVel = p.getVelocity();

        getter.getServer().getScheduler()
                .scheduleSyncDelayedTask(getter, new Runnable() {

                    @Override
                    public void run() {


                        if (pVel.getX() != 0 || pVel.getBlockY() != 0
                                || pVel.getBlockZ() != 0) {
                            getter.hasMoved.remove(p.getName());
                            getter.hasMoved.put(p.getName(), true);
                        } else {
                            getter.hasMoved.remove(p.getName());
                            getter.hasMoved.put(p.getName(), false);
                        }

                    }
                }, 5L);

    }

}

1 个答案:

答案 0 :(得分:2)

没有必要取消任务,因为它已经结束了。我在您的代码中看到了一些问题。第一个也可能是最严重的是你在PlayerMoveEvent中安排一个任务,而不仅仅是那个,但它也是不必要的。使用该事件时,您应始终非常小心。每当玩家移动任何东西时都会调用它,包括他们的头部。因此,该事件每秒可被称为数百次或事件数千次。如果不是绝对必要,您应该始终进行检查,确保玩家移动到新的块以降低代码运行的次数。一个更简单的方法就是做这样的事情:

@EventHandler
public void playerMoves(PlayerMoveEvent e) {
    Player p = e.getPlayer();

    //Check if the player moved to a new block
    if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockY() != e.getFrom().getBlockY() || e.getTo().getBlockZ() != e.getFrom().getBlockZ()) {
        //If they have, set their value in the hashmap to true
        getter.hasMoved.put(p.getName(), true);
    }
}

还要知道,只有在滴答声过去后才会调用您的调度程序,并且程序的其余部分将继续。您可以检查播放器是否已在调度程序中移动

Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {

    @Override
    public void run() {

        if (hasMoved.get(p.getName()) == false) {
            noPVP.remove(p.getName());
            p.sendMessage(ChatColor.YELLOW + "You have turned PVP on!");
        } else {
            p.sendMessage(ChatColor.RED + "You moved so the action was cancelled.");
        }
    }
}, 100L);

另外还有一个简单说明:每次更改其值时,都不需要从HashMap中删除播放器。 HashMap.put()将覆盖现有值。

编辑(另一个建议): 这可能是做到这一点的最好方法,如果你希望在移动后立即实现向播放器发送取消消息的效果,你可以从playerMoves方法中取消调度程序,而不是将播放器添加到HashMap。这样,甚至不需要HashMap,它只会提高整体代码质量。你真的应该尽量避免使用HashMaps,这通常是一种更好的做事方式。