Wait 4 seconds

Discussion in 'Plugin Development' started by Dekuhhh, Oct 12, 2020.

Thread Status:
Not open for further replies.
  1. Offline

    Dekuhhh

    Code:
        public boolean onCommand(CommandSender s, Command cmd, String commandLabel, String[] args) {
           
            Player p = (Player) s;
                if (cmd.getName().equalsIgnoreCase("texture")) {
                    if (!Texture.isEmpty()) {
                        p.sendMessage("§d(!) Wait 5 seconds");
                          // wait 5 seconds and send
                        p.setResourcePack(Texture);
                        p.sendMessage("a");
                } else {
                    p.sendMessage("Al momeno no");
                }
            }
            return false;
        }

    I would like to insert a delay of 5 seconds in the indicated point
     
  2. Offline

    Strahan

    Use a runnable. Whatever you do, do NOT sleep the thread.
     
  3. Offline

    Dekuhhh

    How do I use it? I'm new to java. could you give me an example?
     
  4. Offline

    KarimAKL

    There's examples on the page he linked.
     
  5. Offline

    Strahan

    I have a few mins to kill before a meeting, heh, so I'll show you an example. This is what I'd do:
    Code:
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
      if (!cmd.getName().equalsIgnoreCase("texture")) return true;
      if (!(sender instanceof Player)) {
        sender.sendMessage("Players only!");
        return true;
      }
      if (Texture.isEmpty()) {
        sender.sendMessage("Al momeno no");
        return true;
      }
    
      Player p = (Player)sender;
      p.sendMessage(ChatColor.LIGHT_PURPLE + "(!) Wait 5 seconds");
    
      new BukkitRunnable() {
        @Override
        public void run() {
          p.setResourcePack(Texture);
          p.sendMessage("a");
        }
      }.runTaskLater(this, 100);
    
      return true;
    }
    Now spoonfeeding doesn't help anyone, so I'll explain everything I did:
    Code:
      if (!cmd.getName().equalsIgnoreCase("texture")) return true;
    The first thing I do is check the command, because if it isn't the one I'm interested in no sense in doing anything else. Also, if this is the only command that has its executor set to this class, this is superfluous. Only the command whose executor uses this class will ever see this code, so if it's just /texture it will always be texture so no need to check.

    Code:
      if (!(sender instanceof Player)) {
        sender.sendMessage("Players only!");
        return true;
      }
    You weren't checking if sender (or in your case, s.. try to avoid variable names like that though) is a Player before casting it thus. This is how one does that. Granted, I can't imagine anyone being stupid enough to do texture from console, lol, but I personally prefer to code to avoid any possible errors. If my plugin can cause the code to throw an exception, that offends my sense of programmer pride heh.

    Code:
      if (Texture.isEmpty()) {
        sender.sendMessage("Al momeno no");
        return true;
      }
    I assume Texture is some class scope variable you setup elsewhere. It really should be camelCase not PascalCase though as it's a variable. Sticking to conventions is a good idea. Anyway, I check it first because again if it isn't proper, no sense in continuing. I also check if it's a negative condition instead of positive, so I can throw the error and return. This prevents having a lot of indentation, because if you need to check a lot of conditions as part of a process, your could could potentially end up looking like an arrow lol

    Code:
      p.sendMessage(ChatColor.LIGHT_PURPLE + "(!) Wait 5 seconds");
    I switched from how you used an embedded color character to the ChatColor enum. Don't embed the color character, it's best to use the ChatColor enum. That's what it is there for. If the String you need to colorize is complicated, like having a bunch of colors, an easier method is:
    Code:
      p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&d(!) Wait 5 seconds"));
    That way any & gets replaced with the color char. You may think "well, why not just do (String).replace" to do that? Because if in a later version Mojang changes the character (doubtful though), your plugin will continue to work. If you do the String.replace, it will not colorize.

    Code:
      new BukkitRunnable() {
        @Override
        public void run() {
          p.setResourcePack(Texture);
          p.sendMessage("a");
        }
      }.runTaskLater(this, 100);
    That's the meat of what you need, a runnable. Basically you first run whatever code to be ran immediately before the runnable, then put whatever is to be delayed inside its run method. Sometimes it will bitch that a variable should be final. I'm a Java noob, so I'm not sure what triggers this bitchiness; for example the Player variable I made isn't final yet it worked fine in the runnable. Not sure why, but bear that in mind if you expand functionality of the runnable and hit that.

    After the last } is runTaskLater. There are a variety of other options you can do, like if you want the task to keep repeating there is runTaskTimer for example. But for a simple one shot delay, runTaskLater works. Pass it a plugin instance (this if you run it in the class that extends JavaPlugin, otherwise use an instance of that class) then the second number is the delay - in ticks not milliseconds. 1 second = 20 ticks, so the 5 second delay = 20 * 5 = 100 ticks.

    If you wanted it to repeat, you'd pass the initial delay in ticks then the interval period in ticks. Like:
    Code:
      new BukkitRunnable() {
        @Override
        public void run() {
          p.sendMessage("I'm spamming you!  :P");
        }
      }.runTaskTimer(this, 200, 20);
    So in that example, the code will wait 10 seconds to do anything, then it will start to spam them every second. Now that will run forever, or until the server /reloads. To stop it, you call this.cancel() in the runnable. Example:
    Code:
      new BukkitRunnable() {
        @Override
        public void run() {
          if (p.getLocation().getBlockY() < 64) this.cancel();
          p.sendMessage("I'm spamming you!  :P");
        }
      }.runTaskTimer(this, 200, 20);
    If the player wants the system to shut up, they need to go below sea level then it cancels itself.

    Did that clear it up?
     
    w0lves likes this.
  6. Offline

    Dekuhhh

    Yes, thanks you
     
Thread Status:
Not open for further replies.

Share This Page