1.8.8 Get the Player Count of the Entire Network

Discussion in 'Spigot Plugin Development' started by Dusk_2_Dawn, Feb 15, 2020.

  1. First of all, I'm sorry if this is posted in the wrong section. Its kind of weird because I need help for a Spigot plugin that uses BungeeCord for what I need.

    Anyways, I need to get the player count for the entire network and stick it on a sidebar. The sidebar works fine on it's own, I don't have any issues with it. The issue that I am experiencing is that I just don't know how to get the player counts from all of the servers and combine them for the total players on the network.

    I've tried a few methods from other spigot posts, but they haven't worked at all for me.

    Any ideas?
     
    • Creative Creative x 1
  2. you can use bukkit&bungee plugin message channel and get the playercount using
    Code (Java):
    out.writeUTF("PlayerCount");
    out.writeUTF("ALL"); //use all for all servers or use server name for specific server
    you can read the link above to learn more
     
  3. For loop with Bukkit.getOfflinePlayers() which will register all online and offline players
     
  4. So I tried some options and they aren't really working for me. In my loop to update my scoreboard, I am running a method to send the plugin message:
    Code (Java):
        public void getPlayerCount(Player p) {
            ByteArrayDataOutput out = ByteStreams.newDataOutput();
            out.writeUTF("PlayerCount");
            out.writeUTF("ALL");

            p.sendPluginMessage(main, "BungeeCord", out.toByteArray());
        }
    This is the onPluginMessageReceived method:
    Code (Java):
    @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")) {
                int playerCount = in.readInt();
                setPlayerCount(playerCount);
            }
        }
    And then back in the loop I am getting the player count variable. The only problem is that it is giving me an NPE in Console and it sets the player count to 213324:
    Code (Text):
    [16:58:11 WARN]: Exception in thread "Craft Scheduler Thread - 310"
    [16:58:11 WARN]: org.apache.commons.lang.UnhandledException: Plugin Hub v0.1 generated an exception while executing task 5            
    at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:56)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.NullPointerException
    at net.uprisemc.hub.events.ScoreboardListener$1.run(ScoreboardListener.java:79)  
    at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftTask.run(CraftTask.java:71)  
    at org.bukkit.craftbukkit.v1_8_R3.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)  
    ... 3 more
    https://imgur.com/a/eIInU4y
     
  5. this is because you fail to understand how threading works. you can't set the object in your for loop, because the data does not exist yet. you're sending data on another thread, so the plugin messaging is happening in the background while your for loop is going. because it takes time for messages to send between servers, the data has not yet been set once the logic gets back to the loop. you need to wait for the value to be retrieved thru the pluginmessagereceive event, or update the scoreboard in the pluginmessagereceive event once you get the data.
     
  6. Why don't you just PlaceholderAPI? There's placeholder to get all players inside the bungeecord. %bungee_online%.
     
  7. Everything on the server is custom coded so I would prefer to not have to use an API if I don't have to
     
  8. Get players online, store to a map, and if the number of players online is different, update. It takes a couple of ticks to send the message and receive the player count.
     
  9. This sounds redundant to me. Why not just store an integer? No need to store the players themselves if you're not going to use them.

    This won't do what he wants to do, not to mention if there's a lot of offline players then this could cause a performance impact. You also need to consider that if it's a large network with many hubs that a certain player may not have ever logged into a specific hub at all, hence they won't show up in the offline player cache.

    @OP, you have two ways:
    A) Use the BungeeCord messaging channel and receive players through there.
    B) Use Redis and make it so whenever a player joins/leaves it increments an integer on Redis OR adds/removes their UUID to a set (using sadd/srem) you can use sismember to check if a UUID is in the set. Keep in mind you'd have to store the UUID as either a string or a byte array (string is simplest, but byte array takes up less memory because you're only storing the most significant bits + least significant bits which is 16 bytes.)
    If you use this method, be sure to handle it correctly, ie when the plugin disables clear all the current logged in players on the current server.

    Method A will be more accurate if you're worried that something bad will happen, but method B will also give you a pretty good way of getting all logged-in players on Bungee from Spigot without having to make a BungeeCord channel request. This also works without needing a player online on the current server (because you can't send/receive plugin messages unless there's at least 1 player on the current server.)