Slowing down a While loop WITHOUT Thread.sleep();

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

  1. Just like my title suggests, how would I slow down a While loop WITHOUT using Thread.sleep();? The reason is that it produces A WHOLE lot of errors xD. I don't know another way to do this! My code is:
    Code (Java):
    package me.surprisejedi;

    import org.bukkit.Effect;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.EntityDamageByEntityEvent;

    public class PlayerListener implements Listener {

        public PlayerListener (EventHandle plugin) {
            plugin.getServer().getPluginManager().registerEvents(this,  plugin);

        }

        @SuppressWarnings({ "deprecation", "static-access" })
        @EventHandler
        public void onPlayerHitEvent(final EntityDamageByEntityEvent e) {
            final Entity attacker = e.getEntity();

                while (attacker instanceof Player) {
                    final Player p = (Player) e.getEntity();
                    p.getWorld().playEffect(p.getLocation(), Effect.MAGIC_CRIT, 1);  

            }
        }
    }
     
    Yeah, that's my code. The reason I want to slow down the While loop is because I DONT want the server to crash, AND it there are WAY too many particles when it is run. Any help would be appreciated!
     
    #1 Surprisejedi, Apr 13, 2017
    Last edited: Apr 13, 2017
  2. The attacker is always going to be an instance of a player if a player attacked, you're bringing the server to a halt.
    A while loop is not what you want to be using, instead use an if statement
     
  3. Yeah, the if statement DOES work but I want the particles to never fade away. If i do the if statement then it would only emit one particle
     
  4. You'll have to use a BukkitRunnable to run a task every specified time frame
     
  5. Create an if statement were you check if the player is an attacker and then create a BukkitRunnable. In the runnable the particles will be created every certain amount of time.
     
  6. So kind of like:

    Code (Java):
    package me.surprisejedi;

    import org.bukkit.Bukkit;
    import org.bukkit.Effect;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.EntityDamageByEntityEvent;

    public class PlayerListener implements Listener {

        public PlayerListener (EventHandle plugin) {
            plugin.getServer().getPluginManager().registerEvents(this,  plugin);

        }

        @SuppressWarnings({ "deprecation", "static-access" })
        @EventHandler
        public void onPlayerHitEvent(final EntityDamageByEntityEvent e) {
            Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                public void run() {
                    final Entity attacker = e.getEntity();

                    while (attacker instanceof Player) {
                        final Player p = (Player) e.getEntity();
                        p.getWorld().playEffect(p.getLocation(), Effect.MAGIC_CRIT, 1);

                    }    
                }

            }, 20, 40);

        }
    }
     
    The problem is that it says
    Am I doing something wrong?
     
    #6 Surprisejedi, Apr 13, 2017
    Last edited: Apr 13, 2017
  7. You should create a BukkitRunnable to do this, don't use the BukkitScheduler. Here is why.
    Edit: Whoops, I missed a part of the documentation. You can use the sync method with general Runnables.

    Edit 2: Add an "L" to the end of a number to change it into a long.
     
    #7 JortvD, Apr 13, 2017
    Last edited: Apr 13, 2017
  8. konsolas

    Supporter

    First argument should be a Plugin, not a listener.

    This will still hang the server because the while loop executes on the main thread, and never stops. Think of the runnable as the contents of the while loop - it is executed repeatedly by the scheduler.
     
    • Agree Agree x 1
  9. The BukkitScheduler::runTask methods are not deprecated, and in a lot of cases look nicer than throwaway instances (new Foo().doStuff(), without doing anything with the Foo instance after that)
     
    • Agree Agree x 1
  10. konsolas

    Supporter

    • Agree Agree x 1
  11. Could you please give an example? I am quite new xD
     
  12. This is a good tutorial about scheduler programming.
     
  13. The problem is, I have already tried that. I can't put a public void IN another public void, because of my
    Code (Java):
    public void onPlayerHitEvent(final EntityDamageByEntityEvent e)
     
    #13 Surprisejedi, Apr 13, 2017
    Last edited: Apr 13, 2017
  14. konsolas

    Supporter

    You're not putting a method inside a method. You're putting an anonymous class inside the method, which happens to contain a method. Note:
    Code (Java):
    new Runnable() {
        @Override public void run() { /* ... */ }
    }
    vs just
    Code (Java):

        public void run() { /* ... */ }
     
     
    • Agree Agree x 1
  15. What I was trying to say is that I CANNOT put
    Code (Java):
     public void onPlayerHitEvent(final EntityDamageByEntityEvent e)
    INSIDE the public void run(){}
     
  16. Of course you can't.... I hate to be that person, but please go and learn some basic java before stepping too deep.
     
    • Agree Agree x 1
  17. For god sake, learn Java.
    The run() shall be inside the event :*
     
  18. I am very sorry to be that noob :(
     
  19. maldahleh

    Wiki Team

    It's not that you're a noob, it's that you should look into the Java language before working with an API. It's going to be a lot harder for you to work with the Spigot API if you don't have any background knowledge in the language it is written on.
     
  20. Thread.sleep() sleeps the thread THAT IT IS CALLED IN. So in your case, it's the main thread. Rip your server.