[英]Task not being cancelled when HashMap value is true
我目前正在学习计划任务。
基本上,我正在制作一个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);
}
}
无需取消任务,因为它已经结束。 我的代码中还有一些问题。 首先,可能是最严重的是,您在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,通常有一种更好的处理方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.