FragLand / minestat

:chart_with_upwards_trend: A Minecraft server status checker
GNU General Public License v3.0
352 stars 71 forks source link

Question... How would I make this update every so often? #15

Closed ItsVinnyX closed 6 years ago

ItsVinnyX commented 6 years ago

Question... How would I make this update every so often?

ldilley commented 6 years ago

Greetings, @ItzVinex. This project primarily targets web-based applications. Each time a client with a web browser visits a page, an application may call Minestat to poll a Minecraft server or you can cache the result and update at certain intervals. If you are using this software in another context, cron under Linux/Unix or task scheduler for Windows may be of particular interest if you would like to periodically query arbitrary Minecraft servers. How it is implemented is really up to the end user of Minestat.

What would you like to accomplish?

ItsVinnyX commented 6 years ago

So for my discord bot I have the game status set to the MC server status. But since I set the game once it doesn't update I don't believe.

ldilley commented 6 years ago

In this case, you could create a timer thread that instances a new minestat object (overwriting the previous) every 5 minutes for example. You would then use the relevant Discord API call to update the bot status with the newly-populated minestat object data after this time has elapsed for each iteration.

Which Discord API and language are you using?

ItsVinnyX commented 6 years ago

JDA

ldilley commented 6 years ago

Sorry for the delay. I usually respond after getting off work. In the class file where you are attempting to change the bot status, you would:

import me.dilley.MineStat;

MineStat ms = new MineStat("some.minecraft.server", 25565);

JDA.getPresence().setGame("Playing on " + ms.getAddress() + " with " + ms.getCurrentPlayers() + "/" + ms.getMaximumPlayers() + " players.");

Per the JDA documentation, you may only update the status 5 times per minute maximum. Discord ignores any status changes beyond this rate. You could make a method out of the above and have a thread with a timer periodically call it. If you do not care about blocking, you could also simply wrap the code in a loop along with a call to Thread.sleep() like below.

while(true)
{
  // Query Minecraft server data
  MineStat ms = new MineStat("some.minecraft.server", 25565);
  // Update Discord bot status
  JDA.getPresence().setGame("Playing on " + ms.getAddress() + " with " + ms.getCurrentPlayers() + "/" + ms.getMaximumPlayers() + " players.");
  // Sleep for 30 seconds and update status again
  Thread.sleep(30000);
}

Keep in mind that the above would block. In other words, the bot program would not do anything else as it would be stuck in this loop for the duration of its runtime. If you want the bot to do other things simultaneously such as respond to commands, chat, etc., you would need to create a separate thread that handles the status update periodically. I hope this information is helpful.

ItsVinnyX commented 6 years ago

I'm a little confused on that last part.

Per the JDA documentation, you may only update the status 5 times per minute maximum. Discord ignores any status changes beyond this rate. You could make a method out of the above and have a thread with a timer periodically call it. If you do not care about blocking, you could also simply wrap the code in a loop along with a call to Thread.sleep() like below.

while(true)
{
  // Query Minecraft server data
  MineStat ms = new MineStat("some.minecraft.server", 25565);
  // Update Discord bot status
  JDA.getPresence().setGame("Playing on " + ms.getAddress() + " with " + ms.getCurrentPlayers() + "/" + ms.getMaximumPlayers() + " players.");
  // Sleep for 30 seconds and update status again
  Thread.sleep(30000);
}

Keep in mind that the above would block. In other words, the bot program would not do anything else as it would be stuck in this loop for the duration of its runtime. If you want the bot to do other things simultaneously such as respond to commands, chat, etc., you would need to create a separate thread that handles the status update periodically. I hope this information is helpful.

I would need the bot to respond to commands, chat, etc. I appreciate the help!

ItsVinnyX commented 6 years ago

`public static void main(String[] arguments) throws Exception {

    String server = "";

    MineStatus ms = new MineStatus("play.venomsurge.com", 25565);
    if (ms.isServerUp()) {
        if(Integer.parseInt(ms.getCurrentPlayers()) == 1) {
            server = "VenomSurge " + " with " + ms.getCurrentPlayers() + " player.";
        } else {
            server = "VenomSurge " + " with " + ms.getCurrentPlayers() + " players.";
        }
    } else {
        server = "Server is offline!";
    }
    JDA api = new JDABuilder(AccountType.BOT).setToken("TOKEN").setGame(Game.playing(server)).addEventListener(new MyListener()).addEventListener(new CommandListener()).buildBlocking();

    CommandHandler.commands.put("m", new Music());
    CommandHandler.commands.put("music", new Music());
}`

My current code.

ldilley commented 6 years ago

Your code only initially sets the bot status. Your question pertains much more to the Java language and JDA rather than MineStat. I am just attempting to help you put it all together. Have a look at how to change JDA status and threading in Java. You will want to update the status within a thread. In other words, wrap something like the following in run() as previously mentioned and after reviewing the linked tutorial on threading in Java:

public void run()
{
  while(true)
  {
    // Query Minecraft server data
    MineStat ms = new MineStat("some.minecraft.server", 25565);
    // Update Discord bot status
    JDA.getPresence().setGame("Playing on " + ms.getAddress() + " with " + ms.getCurrentPlayers() + "/" + ms.getMaximumPlayers() + " players.");
    // Sleep for 30 seconds and update status again
    Thread.sleep(30000);
  }
}
ldilley commented 6 years ago

Did you get this working, @ItzVinex? If I do not hear back in 72 hours, I'll assume that you are all set and close this issue.

ItsVinnyX commented 6 years ago

Not yet still struggling.

ldilley commented 6 years ago

No worries. Does this help?

import net.dv8tion.jda.core.*;
import me.dilley.MineStat;

class MineBot implements Runnable
{
  public void run()
  {
    while(true)
    {
      // Query Minecraft server data
      MineStat ms = new MineStat("play.venomsurge.com", 25565);
      // Update Discord bot status
      JDA.getPresence().setGame("Playing on " + ms.getAddress() + " with " + ms.getCurrentPlayers() + "/" + ms.getMaximumPlayers() + " players.");
      // Sleep for 30 seconds and update status again
      try
      {
        Thread.sleep(30000);
      }
      catch(InterruptedException e)
      {
        // handle exception
      }
    }
  }

  public static void main(String[] args) throws Exception
  {
    String server = "";
    MineStat ms = new MineStat("play.venomsurge.com", 25565);
    if(ms.isServerUp())
    {
      if(Integer.parseInt(ms.getCurrentPlayers()) == 1)
      {
        server = "VenomSurge " + " with " + ms.getCurrentPlayers() + " player.";
      }
      else
      {
        server = "VenomSurge " + " with " + ms.getCurrentPlayers() + " players.";
      }
    }
    else
    {
      server = "Server is offline!";
    }
    // Initialize the bot status
    JDA api = new JDABuilder(AccountType.BOT).setToken("TOKEN").setGame(Game.playing(server)).addEventListener(new MyListener()).addEventListener(new CommandListener()).buildBlocking();
    CommandHandler.commands.put("m", new Music());
    CommandHandler.commands.put("music", new Music());
    // Launch thread to periodically update the status
    (new Thread(new MineBot())).start();
  }
}
ItsVinnyX commented 6 years ago

You know what I apologize I got it to work. Thanks for your input!