1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Tutorial What Delays are, and how to work with them

Discussion in 'Tutorials & Resources' started by Snufalufugus, Nov 19, 2017.

  1. Snufalufugus

    Joined:
    Aug 23, 2015
    Messages:
    1,961
    Likes Received:
    757
    Why are delays important at RM:
    Delays are critical to almost any bot in the store. They are what instructs a bot to wait after you attempt an action, rather than looking for something new to do. Without delays, you would be constantly running through your bot's logic, trying to figure out what to do, which would result in incredibly high CPU usage. In addition to this, instead of attempting an action and waiting for it to complete, you would attempt the action over and over again (unless you wrote your bot in a specific way where it would recognize the action was pending).

    Understanding Delays:
    There are three primary types of delays used at Runemate; a delay that is just a certain amount of time, a delay that waits until something happens, and a delay that waits while something is happening. To see all formats, take a look at the Execution class in the javadocs.

    Type 1: Time interval
    This is the most basic type of delay. It just waits a specified amount of time, without regard to anything else. setLoopDelay uses this type of delay by waiting the specified amount of time after each loop of your bot logic. The javadoc's explanation of these delays is more than sufficient as long as you understand that a millisecond is 1/1000th of a second.

    Type 2: Delay Until
    This is what I see as the standard delay. When I need a delay, I almost always delay until something happens. I'll break down the most complex form of Delay Until, since the other forms can be viewed as this with a feature removed.
    [​IMG]

    Let's break this into parts
    • delayUntil - the method name
    • condition - gets checked repeatedly (called) until it is true, at which point the delay will end
    • reset - gets checked repeatedly (called). If it is true, the "timeout" timer returns to 0ms
    • frequency - the interval at which your condition will be called. This defaults to 50ms, and can usually be left out as a parameter, but I'll show it anyways for the tutorial.
    • minTimeout - the minimum allowable time, in milliseconds, that must pass before it will stop calling your condition, and move past the delay. This is used so that if your condition never becomes true, your bot won't be stuck forever.
    • maxTimeout - the maximum allowable time, in milliseconds, that must pass before it will stop calling your condition, and move past the delay. This is used so that if your condition never becomes true, your bot won't be stuck forever.
    Type 3: Delay While
    This can be viewed as an inverted DelayUntil. Instead of delaying until something happens, you delay while it is happening.
    [​IMG]

    Let's break this into parts
    • delayWhile - the method name
    • condition - gets checked repeatedly (called) until it is false, at which point the delay will end
    • reset - gets checked repeatedly (called). If it is true, the "timeout" timer returns to 0ms
    • frequency - the interval at which your condition will be called
    • minTimeout - the minimum allowable time, in milliseconds, that must pass before it will stop calling your condition, and move past the delay. This is used so that if your condition never becomes true, your bot won't be stuck forever.
    • maxTimeout - the maximum allowable time, in milliseconds, that must pass before it will stop calling your condition, and move past the delay. This is used so that if your condition never becomes true, your bot won't be stuck forever.
    You may notice the only difference between a delayUntil and a delayWhile is that instead of it checking for a condition to be true (delayUntil) for the delay to end, it checks for the condition to be false.

    Coding with Delays:
    Now that we have broken delays into easily understood parts, let's take a look at an application of delayUntil and delayWhile.
    Code (Text):
    1. package com.regalbots.woodcutting;
    2.  
    3. import com.runemate.game.api.hybrid.entities.GameObject;
    4. import com.runemate.game.api.hybrid.entities.Player;
    5. import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
    6. import com.runemate.game.api.hybrid.region.GameObjects;
    7. import com.runemate.game.api.hybrid.region.Players;
    8. import com.runemate.game.api.script.Execution;
    9. import com.runemate.game.api.script.framework.LoopingBot;
    10.  
    11. public class OpenSourceTreeChop extends LoopingBot {
    12.  
    13.     GameObject tree; //creates a variable named "tree" of the "GameObject" type
    14.     Player c; //creates a variable named "c" of the "Player" type
    15.  
    16.     @Override
    17.     public void onStart(String... $) {
    18.         setLoopDelay(201, 401); //after each time onLoop is called, there will be a pause of between 0.201sec and 0.401 sec
    19.     }
    20.  
    21.     @Override
    22.     public void onLoop() {
    23.         tree = GameObjects.newQuery().names("Yew tree").results().nearest(); //looks for a nearby tree GameObject and saves it to our "tree" variable
    24.         c = Players.getLocal(); //save our in-game character to the variable c
    25.         if(tree != null && c != null){ //if we found the tree and our character
    26.             if(tree.interact("Chop")) { //if we successfully clicked "Chop" on the tree
    27.                 Execution.delayUntil(() -> Inventory.isFull() || !tree.isValid(), () -> c.getAnimationId() != -1, 50, 1000, 2000);
    28.                 /**Delay Until our inventory is full OR Our tree is no longer there.  Whenever our player is animating, reset the timeout timer.
    29.                  * Check if our inventory is full OR if our tree is no longer there every 50ms, or 20 times per second.
    30.                  * If our timeout timer reaches a random time between 1 and 2 seconds, move past the delay.
    31.                  * */
    32.             }
    33.         } else {
    34.             getLogger().warn("Our tree or player is null"); //print out that our tree was never there, using the "warn" level of logging to bring attention to the message
    35.         }
    36.     }
    37. }
    38.  
    As soon as the delayUntil() method is called, a timer begins. This timer will, at a random time between 1000 and 2000ms from its starting time, force the delay to end. Whenever our player animates something, this starting time is reset. If our inventory becomes full or if the tree goes away, the delay will end.

    The reset condition is crucial here, because if we didn't have it, the bot would re-click on the tree every 1 to 2 seconds, even though we are still chopping it. This is also how you work around activities where you stop animating during them, such as smelting at a furnace.

    Equivalent delayWhile:
    Code (Text):
    1. if(tree.interact("Chop")) { //if we successfully clicked "Chop" on the tree
    2.     Execution.delayWhile(() -> !Inventory.isFull() && tree.isValid(), () -> c.getAnimationId() != -1, 50, 1000, 2000);
    3.     /**Delay while our inventory is not full AND the tree is still there.  Whenever our player is animating, reset the timeout timer.
    4.      * Check if our inventory is full OR if our tree is no longer there every 50ms, or 20 times per second.
    5.      * If our timeout timer reaches a random time between 1 and 2 seconds, move past the delay.
    6.      * */
    7. }
    8.  
    This delay will function in the exact same way as the previous one, since the callable logic has been inverted. Both called conditions have been made opposite, and the OR has been changed to an AND.

    Check your understanding:
    Write a delay that could be used to smelt cannonballs at a furnace. Assume that every four seconds you make four cannonballs, and for one second in between smelting each set of cannonballs your character is standing still. Write this as a delayUntil delay.
    Code (Text):
    1.                 Execution.delayUntil(() -> !Inventory.contains("Steel bar"), () -> c.getAnimationId() != -1, 2000, 4000);
    2.                 /**Delay until we don't have any steel bars to turn into cannonballs.  Whenever we animate something, reset the timeout timer.
    3.                  * By waiting between 2 and 4 seconds after the timeout timer begins to force our bot to move past the delay, we account for the one second
    4.                  * of standing still between smelting sets of cannonballs.  If we didn't have this reset condition, we would either be clicking
    5.                  * on the furnace every 2 to 4 seconds to re-smelt cannonballs, or we would have to have a 135 second timeout condition to
    6.                  * give us time to smelt all the cannonballs.  These are both horrible options since players don't spam click the furnace, and
    7.                  * we don't want to wait over 2 minutes if we somehow are interrupted during our smelting, and never run out of steel bars!
    8.                  * */

    An Extra Feature: Returning a Boolean
    delayUntil and delayWhile also return a boolean that tells you whether or not the delay timed out. If it returns true, it means the callable condition was met. If it returns false, it means the delay timed out. You can use this information if you're creative!
     
    #1 Snufalufugus, Nov 19, 2017
    Last edited: Nov 22, 2017
  2. awesome123man

    awesome123man Go check out new bots and give helpful feedback.

    Joined:
    Jan 31, 2016
    Messages:
    5,413
    Likes Received:
    1,662
    Also, as far as i know the default frequency is 50ms :)
     
  3. Snufalufugus

    Joined:
    Aug 23, 2015
    Messages:
    1,961
    Likes Received:
    757
    Thanks, I'll add that info in. I never use freq param lol.
     
    awesome123man likes this.
  4. TYG123

    Joined:
    Nov 30, 2023
    Messages:
    21
    Likes Received:
    0
    bump because this is super helpful for noobs like me
     

Share This Page

Loading...