Question

I have the following code

@EventHandler
public void onPlayerQuit(PlayerQuitEvent event){
    Player player = event.getPlayer();
    final Player[] playerlist = getServer().getOnlinePlayers();
    if (playerlist.length <=1) { // if no players are online
        getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
            // this is a scheduler.
            public void run(){
                 if(playerlist.length <=1){
                     getServer().shutdown();
                 }
            }
        }, 6000L); // runs every 6000 ticks, which is every 300 seconds, which is every 5 minutes.
 }
}

Which when a player leaves, it checks to see if he was the last one on, if he was, then it after 5 minutes, it checks again, and if still no one is on its supposed to stop the server.

In this line here:

if (playerlist.length <=1) { // if no players are online

I HAVE to have it as <=1 or it doesnt work at all, but it will also stop the server if I leave, and join back and im the only one on. When I had it at =0 and just <1 it didnt work.

Any ideas?

Here is my update code (Still doesnt work):

 @EventHandler
public void onPlayerQuit(PlayerQuitEvent event){
    Player player = event.getPlayer();
    final Player[] playerlist = getServer().getOnlinePlayers();
    if (playerlist.length <=1) { // if no players are online
        getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
            // this is a scheduler.
            public void run(){
                final Player[] playerlist = getServer().getOnlinePlayers(); 
                if(playerlist.length <=1){
                     getServer().shutdown();
                 }
            }
        }, 500L); // runs every 6000 ticks, which is every 300 seconds, which is every 5 minutes.
 }
}
Was it helpful?

Solution

The reason why what you have written does not work is your use of <=. If someone logs off and no one is left, the task is scheduled. If someone logs back on within 5 minuets or less and remains online, when the scheduled task checks to see if the server should be shutdown, 1 <= 1 is true so the server shuts down.

You mentioned that just using = did not work, this is because in boolean statements, == must be used to check for equality.

Try using this:

if (playerlist.length == 0) { // if no players are online
    // Do stuff
}

Update (Discussed in comments): I do not know the Bukkit API very well, but this is what I assume is happening then: The online player list is updated after onPlayerQuit() is executed. Try this: Inside of your onPlayerQuit() method, try checking playerlist.length == 1 and inside of your task, check playerlist.length == 0

OTHER TIPS

I do not know if you have already solved this problem, but I think part of the problem is that you are trying to re-initialize an already initialized final variable...Again, like some of the others in the replies, I do not know Bukkit API as I am trying to learn it, but you cannot re-initialize a final variable...So I would either recommend taking away the final part, or if it must remain, I would make a new array for the run() method...as you are checking for a second time to see if anyone is online...it will not matter if you change arrays, because you are changing amount of players online presumably anyways...because it is final, it will always be 1 when you re-run the length of the final array of playerlist...

You code doesn't refresh the playerlist variable when the delayed task in run, never detecting if someone has joined when the task is actually run.

A better implementation of the code would be:

@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
    Player player = event.getPlayer();
    boolean playersOnServer = false;
    for(Player p : getServer().getOnlinePlayers()) {
        if(p==player) continue;
        playersOnServer = true;
        break;
    }
    if (!playersOnServer) {
        getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
            public void run(){
                //Redo players check
                boolean playersOnServer = false;
                for(Player p : getServer().getOnlinePlayers()) {
                    playersOnServer = true;
                    break;
                }
                if(!playersOnServer){
                    getServer().shutdown();
                }
            }
        }, 6000L);
    }
}

Inside the above code, I used a for loop instead of a simple check to see if there are any players online, to make it work with the old player array from the old bukkit, and the new collections method from the new bukkit.

This kind of detection still has its bugs, for example if the last person quits, then directly joins, and then waits 4 minutes and 59 seconds before leaving again, it will shut down the server directly when he has left.

You never cancel the task when someone logs back on. Since you never cancel the task it will execute even if someone logs back on within the 5m time frame.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top