【问题标题】:Bukkit - Using static variables causing problemsBukkit - 使用静态变量导致问题
【发布时间】:2016-06-16 23:39:31
【问题描述】:

所以我正在开发这个插件,我将解释该功能,以便您了解它的用途:
-/showcps : 每当指定玩家左/右点击时通知发送者

所以,假设有两个玩家 Bob 和 Billy 在运行这个插件的服务器上; Bob 执行命令/showcps Billy 并看到Billy 点击的任何时候。然后比利键入命令/showcps Bob,现在比利看到鲍勃点击的时间。问题是 Bob 无法再看到 Billy 何时点击。

这是我的问题。我想我知道它为什么会发生,但我不知道如何解决它。我使用了全局变量,以便能够在点击侦听器和命令执行器类之间互换使用它们。

这是监听器的代码:

@
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.");
    }
  }
}

这里是命令执行器的代码:

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;
  }
}

如您所见,receivingPlayertargetPlayer 在两个类之间使用,但我觉得这就是它们不能同时观看不同点击的原因。

我该如何解决这个问题?

【问题讨论】:

    标签: java bukkit


    【解决方案1】:

    我建议你在进入 Bukkit 之前学习 java,因为这段代码有严重的问题。

    您的问题出现了,因为您有 1 变量来存储接收播放器和发送播放器。这样,如果您更改它,那么旧的接收播放器将不会收到任何新消息。使用一个hashmap,发送玩家的UUID作为key,接收玩家的UUID作为value,然后当玩家在地图中时,向其对应的接收者发送消息。

    yoir 代码中的其他问题:

    不要滥用静态,这是一种不好的做法,使用 getter 和 setter。

    用 == 而不是 .equal 比较枚举

    插件中的事件类型应该只有 1 个事件处理程序。

    永远不要存储完整的播放器对象,如果你不够小心,它们会导致内存泄漏。

    args[0].isEmpty() 只检查,如果 args[0] 等于一个 emoty 字符串,如果玩家没有指定参数,那么这将抛出一个错误。

    这些问题与我们在http://bukkit.org 论坛上 90% 的时间遇到​​的问题相同。使用该论坛解决基于 Bukkit 的问题,人们可以在那里提供更多帮助。

    【讨论】:

    • 谢谢,我完全忽略了 setter 和 getter。我要揭穿几件事只是为了让自己感觉更好,哈哈。我已经学了相当多的java,我先学了java。 bukkit 需要一些时间来适应。首先,我为什么不应该使用.equal?你能引导我找到关于这个主题的帖子吗?另外,我在那个类中有 2 个事件处理程序,因为出于某种原因 bukkit 不喜欢RIGHT_CLICK_AIR,我想我会尝试用另一个事件处理程序来修复它。 :P
    • 当你说从不存储完整的播放器对象你是什么意思? args[0].isEmpty() 给了我一个错误,但我专注于解决我首先注意到的问题,所以我会回去改变它。我知道我的代码看起来很糟糕,但我通常做的是编写程序,确保它工作,然后返回并优化它的可读性、稳定性和性能。但是,是的,再次感谢!
    • @Kaelinator 枚举是单例,您可以在它们上使用 == ,这样更快。然而,这对于其他对象是不一样的。 Bukkit 有 right_click_air 的问题。千万别这样,它很快就会失控,而且你以后无法正确优化它。
    • @Kaelinator 当我说“从不存储完整的播放器对象”时,我的字面意思是您不应该将它们存储在数组/数组列表/变量中,因为它们占用了大量空间。
    • 我应该如何存储它们,我可以用什么来代替RIGHT_CLICK_AIR
    猜你喜欢
    • 2014-12-09
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 2012-10-04
    • 1970-01-01
    相关资源
    最近更新 更多