0

I'm making a plugin for my Minecraft server which updates an API every 5 seconds with the amount of players online. Every time the server starts up, it gets stuck while enabling the plugin.

This is the function:

public static void playerListLoop(String status, int onlinePlayers) {

        Boolean on = true;

        try {
            while (on = true) {

                try {
                    URL url = new URL("http://192.168.1.14:3000");
                    connection = (HttpURLConnection) url.openConnection();

                    connection.setRequestMethod("POST");
                    connection.setConnectTimeout(5000);
                    connection.setReadTimeout(5000);
                    connection.setRequestProperty("Content-Type", "application/json");
                    connection.setRequestProperty("x-_id", "518747784");
                    connection.setRequestProperty("x-api-key", "7");
                    connection.setDoOutput(true);
                    String urlParameters = "{\"survival\": {\"status\": \"" + status + "\", \"players\": \"" + onlinePlayers + "\"}}";
                    byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);

                    try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())){
                        wr.write(postData);
                    }

                    StringBuilder content;

                    try (BufferedReader br = new BufferedReader(
                            new InputStreamReader(connection.getInputStream()))) {
                        String line;
                        content = new StringBuilder();

                        while ((line = br.readLine()) != null) {
                            content.append(line);
                            content.append(System.lineSeparator());
                        }
                    }

                } catch (ProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    connection.disconnect();
                }
                Thread.sleep(5 * 1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

Thanks in advance!

  • Does your InputStream return a `null` when there is no more input? Isn't `readLine` a blocking operation - won't it wait for next input? – Amongalen Jan 07 '21 at 09:55
  • very true, would I put an else statement under the while != null. and if so what would i put in it – Pointy Kone Jan 07 '21 at 09:59
  • Does this answer your question? [How to identify end of InputStream in java](https://stackoverflow.com/questions/5562370/how-to-identify-end-of-inputstream-in-java) – Amongalen Jan 07 '21 at 10:07
  • that doesn't explain how to end an input stream – Pointy Kone Jan 07 '21 at 10:10

1 Answers1

0

Like @Amongalen said your method playerListLoop() is a blocking operation. See, you start a while loop, but the loop in your code goes on forever as neither your on variable gets changed, nor there is something like break;. That means your plugin gets stuck in this method.

What you need to do is either create a new thread and have your loop run in that thread, or (and what I would recommend) you use the BukkitScheduler prebuild into Spigot.


Sync Tasks

First we save the id so we will be able to cancel the task again:

int taskID;

Then we create our task:

  • For that you need an instance of the class extending JavaPlugin.
  • I use a lambda expression here, but you can also refer to a method.
  • In this case, the 0 is the delay in in game ticks
  • And the 100 is the time in ticks between every loop (1 second = 20 ticks)
taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(YourClass.instance, () -> {
    // update your API
}, 0, 100);

To cancel your task you do:

Bukkit.getScheduler().cancelTask(taskID);

Async Tasks

If you want your task to be async you need to do it a bit different.

This time we save our task using the BukkitTask interface:

BukkitTask task;

Then it's quite similar to sync tasks:

task = Bukkit.getScheduler().runTaskTimerAsynchronously(YourClass.instance, () -> {
    // update your API
}, 0, 100);

And to cancel the task you then do:

task.cancel();
david072
  • 58
  • 2
  • 7