Solved Getting player count from all bungeed servers

Discussion in 'Spigot Plugin Development' started by Plochem, Aug 21, 2019.

  1. Hi, currently I have code that correctly gives me the player count from any bungeed server I specify.

    My question is: how can i wait until I get the player counts from ALL the servers so that I can open a game menu for the player? Right now, the player count is still 0 in the menu.


    Code (Java):
        private int playerCount = 0;

        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if(sender instanceof Player) {
                Player p = (Player)sender;
                if(cmd.getName().equalsIgnoreCase("server")) {
                    getPlayerCount("skyblock", p);
                    Inventory i = Bukkit.createInventory(null, 9, "Game Menu");
                    ItemStack item = new ItemStack(Material.GRASS);
                    ItemMeta itemMeta = item.getItemMeta();
                    itemMeta.setDisplayName("§aSkyblock");
                    itemMeta.setLore(Arrays.asList("", "§7Click to join the Skyblock server.", "" , "§a" + playerCount + " §7players currently online"));
                    item.setItemMeta(itemMeta);
                    i.setItem(2, item);
                 
                    getPlayerCount("survival", p);
                    item.setType(Material.REDSTONE);
                    itemMeta = item.getItemMeta();
                    itemMeta.setDisplayName("§4Ourcraft");
                    itemMeta.setLore(Arrays.asList("", "§7Click to join the survival server.", "" , "§a" + playerCount + " §7players currently online"));
                    item.setItemMeta(itemMeta);
                    i.setItem(6, item);
                 
                    p.openInventory(i);
                 
                }
            }
            return false;
        }

        @Override
        public void onPluginMessageReceived(String channel, Player player, byte[] message) {
            if (!channel.equals("BungeeCord")) {
                return;
            }
            ByteArrayDataInput in = ByteStreams.newDataInput(message);
            String subchannel = in.readUTF();
            if (subchannel.equals("PlayerCount")) {
                in.readUTF();
                playerCount = in.readInt();
                System.out.println(playerCount); // prints out correctly
            }

        }

        private void getPlayerCount(String server, Player p) {
            ByteArrayDataOutput out = ByteStreams.newDataOutput();
            out.writeUTF("PlayerCount");
            out.writeUTF(server);
            p.sendPluginMessage(Core.getPlugin(Core.class), "BungeeCord", out.toByteArray());
        }
     
  2. x86

    x86

    out.writeUTF("GetServers");

    String[] serverList = in.readUTF().split(", ");

    Then just use PlayerCount for all the servers and save it to a map and use it for your gui
     

  3. is there a way to get all the player counts once in the #onPluginMessageReceived method? I want to open the inventory after I get all the player counts.
     
  4. x86

    x86

    I don't think you can get a map directly from bungeecord with the keys being servers and the values being player counts unless you make a custom bungee cord plugin that does that.
     
  5. Just use ProxyServer.getInstance().getServer().getServerInfo().getOnlineCount() (not rlly sure, it's something like that)
     
  6. You could create a HashMap<String (server), Integer (playercount)> and then just adding all the integers together at the end.

    This will not work as OP is not creating a Proxy plugin
     
  7. So for a bungee plugin, do i create a messaging channel so my spigot plugin can communicate with it to get the player count?
     
  8. Hello, a possible solution is by having a Map<String, Integer> where the ServerName would be the key and the integer would be the player count.

    When you want to get all active players, you'd set all the server names (which you'd get with GetServers) to 0.
    When you receive a response in your onPluginMessageReceived, you'd update the map and check if all the server keys are present, if so then you've reached the last server and you can total the values up.


    (Essentially what @Sagacious proposed)
     
    • Agree Agree x 1
  9. ok. so this is what I have, but the player count always returns null.

    Code (Text):

    public class GameMenuCommand implements CommandExecutor, PluginMessageListener{
        private Map<String, Integer> pCount = new HashMap<>();
     
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if(sender instanceof Player) {
                Player p = (Player)sender;
                if(cmd.getName().equalsIgnoreCase("server")) {
                    getPlayerCount("lobby", p);
                    getPlayerCount("skyblock", p);
                    getPlayerCount("survival", p);
                    System.out.println(pCount.get("lobby")); // null
                    System.out.println(pCount.get("skyblock")); // null
                    System.out.println(pCount.get("survival")); // null

                }


            }

            return false;
        }

        @Override
        public void onPluginMessageReceived(String channel, Player player, byte[] message) {
            if (!channel.equals("BungeeCord")) {
                return;
            }
            ByteArrayDataInput in = ByteStreams.newDataInput(message);
            String subchannel = in.readUTF();
            if (subchannel.equals("PlayerCount")) {
                String server = in.readUTF();
                int playerCount = in.readInt();
                pCount.put(server, playerCount);
               System.out.println(pCount.get("lobby")); // NOT null
                System.out.println(pCount.get("skyblock")); // NOT null
                System.out.println(pCount.get("survival")); // NOT null[/COLOR][/LEFT]
            }

        }

        private void getPlayerCount(String server, Player p) {
            ByteArrayDataOutput out = ByteStreams.newDataOutput();
            out.writeUTF("PlayerCount");
            out.writeUTF(server);
            p.sendPluginMessage(Core.getPlugin(Core.class), "BungeeCord", out.toByteArray());
        }

    }
     
    Here's where i register the messaging listener thing. It's in the class that extends JavaPlugin.
    Code (Text):
            this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
            this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new GameMenuCommand());
     
  10. Try setting a delay before immediately getting the values.
     
  11. I created a runnable that prints out the keys and objects every tick, and it's always null.

    BUT, when i place the runnable inside the #onPluginMessageReceived method, it returns the right numbers
     
    #11 Plochem, Aug 22, 2019
    Last edited: Aug 22, 2019
  12. I fixed it. It's because i created two new GameMenuCommand objects: 1 for the command executor and another one for the channel registering.
     
  13. Thanks for not closing this.

    I suggest you to make your plugin message listener in other class and use a dependency injection to retrieve the map into the class where you're doing your command. That way you won't have the spaghetti you have right now.