问题
So I've got this plugin I'm working on, I'll explain the feature so that you get an idea of what it's suppose to do:
-/showcps : tells the sender whenever the specified player left/right clicks
So, let's say there are two players, Bob and Billy on a server running this plugin; Bob does the command /showcps Billy
and sees whenever Billy clicks. Then Billy types the command /showcps Bob
, and now Billy sees when Bob clicks. The problem is that Bob can no longer see when Billy is clicking.
That's my problem. I think I know why it happens, but I'm not sure how to fix it. I used global variables to be able to use them interchangeably between the click listener and command executor classes.
Here's the code for the listeners:
@
EventHandler
public void leftClick(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (event.getAction().equals(Action.LEFT_CLICK_AIR) | event.getAction().equals(Action.LEFT_CLICK_BLOCK)) {
if (player.equals(ClickViewToggle.targetPlayer)) {
ClickViewToggle.recivingPlayer.sendMessage(
ChatColor.LIGHT_PURPLE + player.getName() + ChatColor.DARK_PURPLE + " left clicked.");
}
}
}
@
EventHandler
public void rightClick(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (event.getAction().equals(Action.RIGHT_CLICK_AIR) | event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
if (player.equals(ClickViewToggle.targetPlayer)) {
ClickViewToggle.recivingPlayer.sendMessage(
ChatColor.LIGHT_PURPLE + player.getName() + ChatColor.DARK_PURPLE + " right clicked.");
}
}
}
Here is the code for the command executor:
public static Player targetPlayer = null;
public static Player recivingPlayer;
public boolean onCommand(CommandSender sender, Command command, String cmd, String[] args) {
recivingPlayer = (Player) sender;
if (args[0].isEmpty()) {
if (sender instanceof Player) {
sender.sendMessage(ChatColor.DARK_PURPLE + "You will now be able to see your clicks.");
targetPlayer = (Player) sender;
return false;
} else {
sender.sendMessage(ChatColor.DARK_PURPLE + "You must specify a player.");
return false;
}
} else {
boolean playerFound = false;
for (Player player: Bukkit.getServer().getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(args[0])) {
sender.sendMessage(ChatColor.DARK_PURPLE + "You are now seeing " + ChatColor.LIGHT_PURPLE + player.getName() + ChatColor.DARK_PURPLE + "\'s clicks.");
targetPlayer = player;
playerFound = true;
break;
}
}
if (!playerFound) {
sender.sendMessage(ChatColor.DARK_PURPLE + "Couldn't find " + ChatColor.LIGHT_PURPLE + args[0] + ChatColor.DARK_PURPLE + ".");
targetPlayer = null;
}
return false;
}
}
As you can see, receivingPlayer
and targetPlayer
are used between the two classes, but I feel like that's the reason that they both can't watch different clicks at the same time.
How can I fix this?
回答1:
I'd advise you to learn java before diving into Bukkit, because this code has serious problems.
Your problem occurs, because you have 1 variable to store the receiveng player and the sending player. This way, if you change it, then the old receiving player won't get any new messages. Use a hashmap with the sending player's UUID as key and the receiving player's UUID as value, then when a player is in the map, send a message to his corresponding receiver.
The other problems in yoir code:
Don't abuse static, it's a bad practice, use getters and setters.
Compare enums with == instead of .equal
You should have only 1 eventhandler for an event type in your plugin.
Never store full player objects, they cab cause a memory leak, if you're not careful enough.
args[0].isEmpty()
only checks, if args[0] equals to an emoty string, if the player doesn't specify an argument, then this will throw an error.
These are the same kind of problems we at the http://bukkit.org forums encounter 90% of the time. Use that forum for Bukkit based questions, people can help more there.
来源:https://stackoverflow.com/questions/37871036/bukkit-using-static-variables-causing-problems