Getting a Random Player That Is Online

Discussion in 'Spigot Plugin Development' started by Username1234, Apr 13, 2017.

  1. This is what I tried:
    Code (Text):
    int random = new Random().nextInt(Bukkit.getOnlinePlayers().length);
    Player player = Bukkit.getOnlinePlayers()[random];
    But it does not work: http://prntscr.com/ew6133

    How would I fix this/is there a more efficient way to do this?
     
    • Like Like x 1
  2. NathanWolf

    Supporter

    getOnlinePlayers returns a Collection now. Unfortunately that interface doesn't let you get by index...

    You can use .size() to replace .length

    But in order to use .get(index) you would need to cast it to a List. Which seems like for now could be safe, but who knows if they might change it to some other Collection in the future.

    Maybe there's a better way (without copying the whole thing into a List or array).
     
  3. So what would I change? I changed length.
     
  4. NathanWolf

    Supporter

    Uh, I guess ((List)Bukkit.getOnlinePlayers()).get(random);

    Seems like a really bad idea though.
     
  5. To make things much cleaner, do something like this
    Code (Text):
    ArrayList<String> allPlayers = new ArrayList<String>();
    for(Player players : Bukkit.getOnlinePlayers()) {
    allPlayers.add(players);
    }
    int random = new Random().nextInt(allPlayers.size());
    Object picked = allPlayers.get(random);
    Then you could get that object, use a variable and convert it to Player and broadcast it or do whatever with it
    Funny, I was working with randoms last night!
     
    • Agree Agree x 1
    • Informative Informative x 1
  6. NathanWolf

    Supporter

    ArrayList<String> allPlayers = new ArrayList<String>(Bukkit.getOnlinePlayers());

    Is a little cleaner, too :)
    Not super efficient though, depends on how often you need to do this. I agree it's cleaner than making assumptions about what getOnlinePlayers really returns, though.
     
  7. Oh! You could do allPlayers.clear() after the code, I just want to show him the jist
     
  8. FrostedSnowman

    Resource Staff

    Code (Java):
    Player player = Bukkit.getOnlinePlayers().stream().skip((int) (Bukkit.getOnlinePlayers().size() * Math.random())).findFirst().orElse(null);
     
    • Like Like x 3
  9. It throws this error:
    Code (Text):
    [18:32:47 ERROR]: Could not pass event PlayerJoinEvent to JoinPriorities v1.0.0
    org.bukkit.event.EventException
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.PlayerList.onPlayerJoin(PlayerList.java:298) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.PlayerList.a(PlayerList.java:157) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.LoginListener.b(LoginListener.java:144) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.LoginListener.c(LoginListener.java:54) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.NetworkManager.a(NetworkManager.java:231) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.ServerConnection.c(ServerConnection.java:148) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:814) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot.jar:git-Spigot-21fe707-e1ebe52]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_121]
    Caused by: java.lang.NullPointerException
            at me.demeng7215.jp.listeners.JoinEvent.onJoin(JoinEvent.java:33) ~[?:?]
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_121]
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_121]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_121]
            at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_121]
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot.jar:git-Spigot-21fe707-e1ebe52]
            ... 14 more
    I am using this code:
    Code (Text):
    package me.demeng7215.jp.listeners;

    import java.util.Random;

    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerJoinEvent;

    import me.demeng7215.jp.Main;

    public class JoinEvent implements Listener {
     
        String prefix = Main.getInstance().getConfig().getString("prefix");
     
        @EventHandler(priority = EventPriority.HIGH)
        public void onJoin(PlayerJoinEvent e) {
         
            if(Bukkit.getServer().getOnlinePlayers().size() >= Main.getInstance().getConfig().getInt("max_players")) {
             
                for(Player players : Bukkit.getOnlinePlayers()) {
                     
                    Main.allPlayers.add(players.toString());
                }
             
                int random = new Random().nextInt(Main.allPlayers.size());
                Object picked = Main.allPlayers.get(random);
             
                Player p = Bukkit.getServer().getPlayer((String) picked);
             
                if(!p.hasPermission("joinpriority.priority") || !p.isOp()) {
             
                p.kickPlayer(Main.color(prefix + Main.getInstance().getConfig().getString("kick_message")));
                Bukkit.broadcastMessage(Main.color(prefix + Main.getInstance().getConfig().getString("broadcast")));
                }
            }
        }
    }
     
  10. How many players joined and or were/are in the arraylist?
    Also, why are you adding the players to a string?! It should get .getName(), toString would look like CraftPlayer("455314fd") <This may be the problem, the player is null because you're getting the picked player but Bukkit can't find that player because it's like CraftPlayer(blahblahblah)
     
  11. FrostedSnowman

    Resource Staff

    fix it then. line 33 is returning a null value / using a null value. also, did u try my suggestion?
     
    • Why are you even keeping a global List of players, just create a new one on the spot.
    • In general, don't abuse static for global access, it turns your code in a heap of spaghetti real fast.
      • If you need access to your main class, pass an instance to the other class (your listener class in this case) through the constructor.
    • Don't create new Randoms whenever you need one, use ThreadLocalRandom instead.
    • Your code is fundamentally flawed as well: if you pick a random player who's OP or has the permission, no one will be kicked.
      • Instead, take the Collection<Player>, and filter all players who pass this criteria (f.e. through a stream-filter-collect chain)
        Code (Java):
        collection.stream().filter(/*your predicate*/).collect(Collectors.toList())
        If you end up with an empty List, kick the joining player instead (since there's no free slot, nor a player to be kicked)
     
  12. I tried that but it was kind of messed up:
    Code (Text):
    package me.demeng7215.jp.listeners;

    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerJoinEvent;

    import me.demeng7215.jp.Main;

    public class JoinEvent implements Listener {
       
        String prefix = Main.getInstance().getConfig().getString("prefix");
       
        @EventHandler(priority = EventPriority.HIGH)
        public void onJoin(PlayerJoinEvent e) {
           
            if(Bukkit.getServer().getOnlinePlayers().size() >= Main.getInstance().getConfig().getInt("max_players")) {
               
                Player p = Bukkit.getOnlinePlayers().stream().skip((int) (Bukkit.getOnlinePlayers().size() * Math.random())).findFirst().orElse(null);          
                if(!p.hasPermission("joinpriority.priority") || !p.isOp()) {
               
                p.kickPlayer(Main.color(prefix + Main.getInstance().getConfig().getString("kick_message")));
                Bukkit.broadcastMessage(Main.color(prefix + Main.getInstance().getConfig().getString("broadcast")));
                Main.allPlayers.clear();
                }
            }
        }
    }
    When a person that is not OP joins, they get kicked when the server has no players. When and OP joins, the 2nd person who join does not get kicked.
    I set the max_players to 1.
     
  13. Just check if the players not op
    Code (Text):
    if(p.isOp() {
    //Do whatever
    } else if(!p.isOp() {
    //Do that code
    Maybe that'll work
     
  14. I also want it to work with permissions.
     
    • Like Like x 1
  15. if(p.hasPermissions("") {
    // YOUR CODE HERE
    }
     
  16. int random = new Random().nextInt(Bukkit.getOnlinePlayers().size());
    Player player = Bukkit.getOnlinePlayers().get(random);
     
  17. Code (Text):
    new BukkitRunnable() {
                @Override
                public void run() {
                   
                    List<Player> players = new ArrayList<>();
                    for (Player online : Bukkit.getOnlinePlayers()) {
                       
                        if (Bukkit.getOnlinePlayers().size() > players.size()) {
                           
                            if (players.contains(online)) {
                               
                                return;
                            }
                           
                            players.add(online);
                           
                            int randomPlayer = new Random().nextInt(players.size());
                           
                            Player player = players.get(randomPlayer);
                        }
                    }
                }
            }.runTaskTimer(plugin, 20L, 20L);