Solved How to return a value from Runnable

Discussion in 'Spigot Plugin Development' started by UnrealMiner4, Jul 8, 2021.

  1. Hey, I'm trying to make a boolean method that checks the player's speed and then, if it is low enough, returns true. The thing is, that to check the speed, you have to wait at least one tick, and for that I use Runnable and runTaskLater thing. After that I want to return true or false, and how do I do it? Here's the code:
    Code (Java):
    public boolean isSlow(Player p) {
            //It gets player's location
            Double x1 = p.getLocation().getX();
            Double z1 = p.getLocation().getZ();
            Runnable r = new Runnable() {
               
                @Override
                public void run() {
                    //It gets player's location after a tick
                    Double x2 = p.getLocation().getX();
                    Double z2 = p.getLocation().getZ();
                    //It calculates his speed
                    Double speedx = Math.abs(x1-x2);
                    Double speedz = Math.abs(z1-z2);
                    //It checks if the speed is low enough
                    if(!(speedx < 0.1011f) && !(speedz < 0.1011f)) {
                        //What do I write here?
                    } else {
                        //...and here
                    }
                }
            };
            Bukkit.getScheduler().runTaskLater(Classes.plugin/*Plugin_Instance*/, r, 1);
        }
    Or maybe if you would recommend me another way to do that, I would really appreciate that!
     
  2. drives_a_ford

    Moderator

    Unfortunately you don't seem to grasp what it is you're doing (and/or attempting to do) exactly.

    You see, when you schedule a runnable task, the code within it will be run the next tick (or at a later time if specified).
    But the code flow will continue on with the current tick up until it gets to the next tick and up until when it gets to the scheduler which finally fires the method.
    So by the time the code within the runnable is executed, the method in question has returned a value long ago ("just" 1 tick ago, but my point is that there's plenty that happens between).

    There's multiple ways you can go about solving this issue.
    1) You could keep track of players' speed all the time. That way you could just use the value you've got stored. Although this might not make a lot of sense if you don't really need the values too often.
    2) You could have the method return a CompletableFuture object and use its CompletableFuture#whenComplete method wherever you need to use the resulting information.
    3) You could have the second half of your logic in a different method and just pass the result from within the runnable to that one.
    4) And many more possibilities depending on the specific problem.
     
  3. Thank you, I will try using CompletableFuture, it looks promising:D