在 PlayerMoveEvent 中只执行一次 p.sendMessage
Execute p.sendMessage only once in PlayerMoveEvent
当 playerMoveEvent 执行时,它会在他每次行走时发送一条取消消息。能不能只发一次?
这是主要内容 class:
package me.mortadelle2.togglePVP;
import java.util.ArrayList;
import java.util.HashMap;
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;
public class PVP extends JavaPlugin{
public int turnOn;
public int turnOff;
ArrayList<String> noPVP = new ArrayList<String>();
HashMap<String, Integer> stepCounter = new HashMap<String, Integer>();
public void onEnable(){
new MainEvents(this);
getLogger().info("You may now toggle PVP!");
}
public void onDisable(){
getLogger().info("You may no longer toggle PVP ;(");
}
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
final Player p = (Player) sender;
if (cmd.getName().equalsIgnoreCase("pvp") && p.hasPermission("togglepvp.toggle")){
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")){
stepCounter.put(p.getName(), 0);
p.sendMessage(ChatColor.RED + "PVP " + ChatColor.YELLOW + "will be turned on in 5 seconds! Don't move!");
turnOn = this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
noPVP.remove(p.getName());
p.sendMessage(ChatColor.RED + "PVP" + ChatColor.YELLOW + " has been turned on!");
}
}, 100L);
return true;
}
if (args[0].equalsIgnoreCase("off") && p.hasPermission("togglepvp.toggle")) {
stepCounter.put(p.getName(), 0);
p.sendMessage(ChatColor.RED + "PVP " + ChatColor.YELLOW
+ "will be turned off in 5 seconds! Don't move!");
turnOff = this.getServer().getScheduler()
.scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
noPVP.add(p.getName());
p.sendMessage(ChatColor.RED + "PVP"
+ ChatColor.YELLOW
+ " has been turned off!");
}
}, 100L);
return true;
}
}
}
return false;
}
}
而听众class:
package me.mortadelle2.togglePVP;
import org.bukkit.ChatColor;
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.player.PlayerMoveEvent;
public class MainEvents implements Listener {
PVP getter;
public MainEvents(PVP plugin){
plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.getter = plugin;
}
@EventHandler
public void playerDamagesWhenToggledOff(EntityDamageByEntityEvent e){
Player victim = (Player) e.getEntity();
Player damager = (Player) e.getDamager();
if (getter.noPVP.contains(victim) || getter.noPVP.contains(damager)){
e.setCancelled(true);
}
}
@EventHandler
public void playerMovesSoCancelsTask(PlayerMoveEvent e){
Player p = e.getPlayer();
getter.stepCounter.put(p.getName(), 1);
if (getter.stepCounter.get(p.getName()) == 1){
if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockY() != e.getFrom().getBlockY()
|| e.getTo().getBlockZ() != e.getFrom().getBlockZ()){
getter.getServer().getScheduler().cancelTask(getter.turnOn);
getter.getServer().getScheduler().cancelTask(getter.turnOff);
p.sendMessage(ChatColor.RED + "You moved so the action was cancelled!");
getter.stepCounter.put(p.getName(), 0);
}
}
}
}
我试过数他的步数并在他走路时递增,但这不起作用,所以我无法想象会发生什么。
您可以先删除您拥有的所有全局变量,然后创建一个 public 静态 ArrayList 用于保存所有已启用 pvp 保护的玩家和一个用于等待更改状态的玩家。
public static ArrayList<String> noPVP = new ArrayList<String>();//Holds players that have pvp protection enabled
public static ArrayList<String> playersWaiting = new ArrayList<String>();//Holds players waiting to change states
static 修饰符将创建一个对象,您可以在整个 classes 中访问该对象,而不必通过执行 PVP.[var] 来拥有主 class 的 'getter' 实例。您可以删除所有其他全局变量,现在由于这些变量是静态的,您可以删除侦听器 class.
中的 getter
要解决您的问题,您需要修改命令以在玩家执行命令时将其置于地图中
if (args[0].equalsIgnoreCase("on")) {
player.sendMessage(ChatColor.YELLOW + "PVP will be turned on in 5 seconds! Don't move!");
playersWaiting.add(player.getName());
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (playersWaiting.contains(player.getName())) {
playersWaiting.remove(player.getName());
noPVP.remove(player.getName());
player.sendMessage(ChatColor.YELLOW + "You have turned PVP on!");
}
}
}, 100L);
return true;
} else if (args[0].equalsIgnoreCase("off")) {
player.sendMessage(ChatColor.YELLOW + "PVP will be turned off in 5 seconds. Don't move!");
playersWaiting.add(player.getName());
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (playersWaiting.contains(player.getName())) {
playersWaiting.remove(player.getName());
noPVP.add(player.getName());
player.sendMessage(ChatColor.YELLOW + "You have turned PVP off!");
}
}
}, 100L);
return true;
}
如果玩家改变位置,您的玩家移动事件应该将玩家从地图中完全移除:
@EventHandler
public void playerMovesSoCancelsTask(PlayerMoveEvent e) {
Player player = e.getPlayer();//Get the player
//Check if the player is moving to a new block
if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockY() != e.getFrom().getBlockY() || e.getTo().getBlockZ() != e.getFrom().getBlockZ()) {
//Check if the player is waiting to turn on/off pvp
if (PVP.playersWaiting.contains(player.getName())) {
player.sendMessage(ChatColor.RED + "You moved so the action was cancelled!");
PVP.playersWaiting.remove(player.getName()); //Remove the player from the waiting list
}
}
}
我注意到的其他一些问题:
1) 你在没有任何检查的情况下将 CommandSender 施放给玩家。尝试从控制台执行命令,看看会发生什么。 google 搜索应该会告诉您如何解决这个问题。
2) 在您的 playerDamagesWhenToggledOff
侦听器方法中,您检查播放器本身,而不是他们的名字。请务必使用他们的名字:if (Main.noPVP.containsKey(victim.getName())) { e.setCancelled() }
3) 永远不要从变量中删除玩家,确保创建一个新的 PlayerQuitEvent
并从所有全局变量中删除玩家。
当 playerMoveEvent 执行时,它会在他每次行走时发送一条取消消息。能不能只发一次?
这是主要内容 class:
package me.mortadelle2.togglePVP;
import java.util.ArrayList;
import java.util.HashMap;
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;
public class PVP extends JavaPlugin{
public int turnOn;
public int turnOff;
ArrayList<String> noPVP = new ArrayList<String>();
HashMap<String, Integer> stepCounter = new HashMap<String, Integer>();
public void onEnable(){
new MainEvents(this);
getLogger().info("You may now toggle PVP!");
}
public void onDisable(){
getLogger().info("You may no longer toggle PVP ;(");
}
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
final Player p = (Player) sender;
if (cmd.getName().equalsIgnoreCase("pvp") && p.hasPermission("togglepvp.toggle")){
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")){
stepCounter.put(p.getName(), 0);
p.sendMessage(ChatColor.RED + "PVP " + ChatColor.YELLOW + "will be turned on in 5 seconds! Don't move!");
turnOn = this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
noPVP.remove(p.getName());
p.sendMessage(ChatColor.RED + "PVP" + ChatColor.YELLOW + " has been turned on!");
}
}, 100L);
return true;
}
if (args[0].equalsIgnoreCase("off") && p.hasPermission("togglepvp.toggle")) {
stepCounter.put(p.getName(), 0);
p.sendMessage(ChatColor.RED + "PVP " + ChatColor.YELLOW
+ "will be turned off in 5 seconds! Don't move!");
turnOff = this.getServer().getScheduler()
.scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
noPVP.add(p.getName());
p.sendMessage(ChatColor.RED + "PVP"
+ ChatColor.YELLOW
+ " has been turned off!");
}
}, 100L);
return true;
}
}
}
return false;
}
}
而听众class:
package me.mortadelle2.togglePVP;
import org.bukkit.ChatColor;
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.player.PlayerMoveEvent;
public class MainEvents implements Listener {
PVP getter;
public MainEvents(PVP plugin){
plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.getter = plugin;
}
@EventHandler
public void playerDamagesWhenToggledOff(EntityDamageByEntityEvent e){
Player victim = (Player) e.getEntity();
Player damager = (Player) e.getDamager();
if (getter.noPVP.contains(victim) || getter.noPVP.contains(damager)){
e.setCancelled(true);
}
}
@EventHandler
public void playerMovesSoCancelsTask(PlayerMoveEvent e){
Player p = e.getPlayer();
getter.stepCounter.put(p.getName(), 1);
if (getter.stepCounter.get(p.getName()) == 1){
if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockY() != e.getFrom().getBlockY()
|| e.getTo().getBlockZ() != e.getFrom().getBlockZ()){
getter.getServer().getScheduler().cancelTask(getter.turnOn);
getter.getServer().getScheduler().cancelTask(getter.turnOff);
p.sendMessage(ChatColor.RED + "You moved so the action was cancelled!");
getter.stepCounter.put(p.getName(), 0);
}
}
}
}
我试过数他的步数并在他走路时递增,但这不起作用,所以我无法想象会发生什么。
您可以先删除您拥有的所有全局变量,然后创建一个 public 静态 ArrayList 用于保存所有已启用 pvp 保护的玩家和一个用于等待更改状态的玩家。
public static ArrayList<String> noPVP = new ArrayList<String>();//Holds players that have pvp protection enabled
public static ArrayList<String> playersWaiting = new ArrayList<String>();//Holds players waiting to change states
static 修饰符将创建一个对象,您可以在整个 classes 中访问该对象,而不必通过执行 PVP.[var] 来拥有主 class 的 'getter' 实例。您可以删除所有其他全局变量,现在由于这些变量是静态的,您可以删除侦听器 class.
中的 getter要解决您的问题,您需要修改命令以在玩家执行命令时将其置于地图中
if (args[0].equalsIgnoreCase("on")) {
player.sendMessage(ChatColor.YELLOW + "PVP will be turned on in 5 seconds! Don't move!");
playersWaiting.add(player.getName());
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (playersWaiting.contains(player.getName())) {
playersWaiting.remove(player.getName());
noPVP.remove(player.getName());
player.sendMessage(ChatColor.YELLOW + "You have turned PVP on!");
}
}
}, 100L);
return true;
} else if (args[0].equalsIgnoreCase("off")) {
player.sendMessage(ChatColor.YELLOW + "PVP will be turned off in 5 seconds. Don't move!");
playersWaiting.add(player.getName());
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (playersWaiting.contains(player.getName())) {
playersWaiting.remove(player.getName());
noPVP.add(player.getName());
player.sendMessage(ChatColor.YELLOW + "You have turned PVP off!");
}
}
}, 100L);
return true;
}
如果玩家改变位置,您的玩家移动事件应该将玩家从地图中完全移除:
@EventHandler
public void playerMovesSoCancelsTask(PlayerMoveEvent e) {
Player player = e.getPlayer();//Get the player
//Check if the player is moving to a new block
if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockY() != e.getFrom().getBlockY() || e.getTo().getBlockZ() != e.getFrom().getBlockZ()) {
//Check if the player is waiting to turn on/off pvp
if (PVP.playersWaiting.contains(player.getName())) {
player.sendMessage(ChatColor.RED + "You moved so the action was cancelled!");
PVP.playersWaiting.remove(player.getName()); //Remove the player from the waiting list
}
}
}
我注意到的其他一些问题:
1) 你在没有任何检查的情况下将 CommandSender 施放给玩家。尝试从控制台执行命令,看看会发生什么。 google 搜索应该会告诉您如何解决这个问题。
2) 在您的 playerDamagesWhenToggledOff
侦听器方法中,您检查播放器本身,而不是他们的名字。请务必使用他们的名字:if (Main.noPVP.containsKey(victim.getName())) { e.setCancelled() }
3) 永远不要从变量中删除玩家,确保创建一个新的 PlayerQuitEvent
并从所有全局变量中删除玩家。