Jump to content
View in the app

A better way to browse. Learn more.

OSBot :: 2007 OSRS Botting

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Custom Sleep Handler

Featured Replies

I have been trying to write an effective custom sleep handler - I have commented through the method to make it clearer what the purpose of each stage is.

I am having trouble with implementation on my latest attempt at a script - I find that when interacting it is tending to spam click when I don't expect that behaviour

Any advice? (also free sample code if anyone can make use of it! :))

 

CS.java

import org.osbot.rs07.utility.ConditionalSleep;
import java.util.Random;
import java.util.function.BooleanSupplier;
import org.osbot.rs07.script.Script;

public class CS extends ConditionalSleep {
    private final BooleanSupplier condition;
    private final Script script;
    private final int initialDurationMs;
    private final int additionalDurationMs;
    private final Random random = new Random();

    public CS(Script script, int initialDurationMs, int additionalDurationMs, BooleanSupplier condition) {
        super(initialDurationMs + additionalDurationMs);
        this.initialDurationMs = initialDurationMs;
        this.additionalDurationMs = additionalDurationMs;
        this.condition = condition;
        this.script = script;
    }

    @Override
    public boolean condition() throws InterruptedException {
        boolean mouseOutOfScreen = false;

        // Small chance to move mouse out of screen immediately
        if (random.nextDouble() < 0.03) {
            script.getMouse().moveOutsideScreen();
            mouseOutOfScreen = true;
        }

        // Capture the external condition to use inside the anonymous class
        BooleanSupplier localCondition = this.condition;

        // Small Sleep after action of ~ 300 - 800ms
        new ConditionalSleep(300 + random.nextInt(800 - 300), 100) {
            @Override
            public boolean condition() {
                return localCondition.getAsBoolean();
            }
        }.sleep();


        if(localCondition.getAsBoolean()) {

            // Small chance to move mouse out of screen after small wait
            if (random.nextDouble() < 0.10 && !mouseOutOfScreen) {
                script.getMouse().moveOutsideScreen();
                mouseOutOfScreen = true;
            }

            // Sleep after the event is already true
            new ConditionalSleep(this.additionalDurationMs, 100) {
                @Override
                public boolean condition() {
                    return false;
                }
            }.sleep();

        }
        else {
            // Larger chance to move mouse out of screen after the condition is still not true
            if (random.nextDouble() < 0.50 && !mouseOutOfScreen) {
                script.getMouse().moveOutsideScreen();
                mouseOutOfScreen = true;
            }

            // Sleep until the event is true, or until the timeout
            new ConditionalSleep(this.initialDurationMs, 100) {
                @Override
                public boolean condition() {
                    return localCondition.getAsBoolean();
                }
            }.sleep();


            // Sleep after the event is already true
            new ConditionalSleep(this.additionalDurationMs, 100) {
                @Override
                public boolean condition() {
                    return false;
                }
            }.sleep();

        }
        return true;
    }

}


here is one example from the main script: (immediately inside onLoop method)
for clarity:
V just stores variables like V.worldBank is an area
fatigueHandler is exactly what it sounds like - handles fatigue over time whilst playing which impacts the ms times it returns

The minimum value for getSleepTimeMs() is 41ms

However, clearly, from the script usage below, you can see that on bank.interact, it will either:


1) timeout after 5 seconds (in which case I haven't actually handled it yet)

2) succeed, in which case, it won't spam click anyway, since the bank will be open?

Neither of these two possibilities involve spam clicking?  Really appreciate any tips and advice on this
 

if(V.worldBank.contains(myPlayer().getPosition()) && state == StateEngine.State.BANKING) {
    if(!getBank().isOpen()){
        RS2Object bank = getNearestBank();
        if(!bank.exists()){
            log("Bank does not exist. Exiting.");
            onExit();
        }
        bank.interact("Bank");

        new CS(this, 5000, fatigueHandler.getSleepTimeMs(), () -> getBank().isOpen());

        getBank().depositAll();

        new CS(this, 3000, fatigueHandler.getShortSleepTimeMs(), () -> getInventory().isEmpty());

        getBank().withdraw("Adamant pickaxe", 1);

        new CS(this, 3000, fatigueHandler.getShortSleepTimeMs(), () -> getInventory().contains("Adamant pickaxe"));

        getBank().close();

        new CS(this, 3000, fatigueHandler.getShortSleepTimeMs(), () -> !getBank().isOpen());

        return 20;
    }
}

 

Off topic, but bonus if anyone knows; regards random events, is there a way to implement only some specific ones and ignore the others? It seems awfully bot-like to just ignore all of them, particularly the genie and the free stuff ones like rick terpentine - don't want to solve any stupid events, but I know if I am playing legit I will just talk to those ones to get free stuff, would like to emulate that

What is the purpose of this? Is it to add a bit of extra delay after preforming any action along with potentially moving the mouse offscreen?

  • Author

Yeah that is basically the reason for it - for convenience I was hoping to make a more complex sleep so I can write (or copy-paste) less of my code

Since this doesn't seem to work, I am currently writing out the ConditionalSleep, then adding additional sleeps after, and writing the mouse offscreen code each time, which, given the amount of sleeps code tends to do, is annoying!

Trying to just call a single function that performs a sleep-cycle the way I want it to sleep - I can then make the function do things like consider fatigue  & high intensity play periods, mouse offscreen, and even occasionally AFK-log, only by writing a simple function call

I'm pretty new to Java tbh, it is not easy!

 

1 hour ago, Fanny said:

Yeah that is basically the reason for it - for convenience I was hoping to make a more complex sleep so I can write (or copy-paste) less of my code

Since this doesn't seem to work, I am currently writing out the ConditionalSleep, then adding additional sleeps after, and writing the mouse offscreen code each time, which, given the amount of sleeps code tends to do, is annoying!

Trying to just call a single function that performs a sleep-cycle the way I want it to sleep - I can then make the function do things like consider fatigue  & high intensity play periods, mouse offscreen, and even occasionally AFK-log, only by writing a simple function call

I'm pretty new to Java tbh, it is not easy!

 

You can  add some log statements into your CS class to debug what is failing.

Alternatively do what you are currently doing with...
I am currently writing out the ConditionalSleep, then adding additional sleeps after, and writing the mouse offscreen code each time

but separate it out into a static utility method. I have this class that does something along the same lines. It just reattempts something up to n times as there can be race conditions with opening an interface, waiting for the interface actually becoming usable ingame, and attempting to interact with a widget in the interface. 

public class RetryUtil {
    public static boolean retry(Callable<Boolean> fx, int maxAttempts, int retryWaitTime) throws InterruptedException {
        int attempts = 0;
        boolean isSuccess = false;
        while (attempts < maxAttempts) {
            try {
                isSuccess = fx.call();
            } catch (Exception ignored) {
            }
            attempts++;
            if(isSuccess) {
                break;
            }
            MethodProvider.sleep(retryWaitTime);
        }
        return isSuccess;
    }


ex usage

RetryUtil.retry(() -> bank.withdraw(itemId, amount), 5, 1000)


You can try making something similar where you pass in a Callable that has some code you want to run (like bank.open()). Sleep until it is open, then  roll to sleep a bit more + move the mouse offscreen. 

  • Author

Thanks! I think this is probably where I am getting stuck, static vs. non-static is a bit confusing to me still

I'll try adapting this to suit my use cases & let you know how I get on :)

On 5/20/2024 at 5:27 AM, Fanny said:

Thanks! I think this is probably where I am getting stuck, static vs. non-static is a bit confusing to me still

I'll try adapting this to suit my use cases & let you know how I get on :)

Here's a link to help help explain the difference between static and non-static methods.

https://www.geeksforgeeks.org/difference-between-static-and-non-static-method-in-java/

Edited by BravoTaco

  • Author
On 5/20/2024 at 11:12 AM, yfoo said:

public class RetryUtil {

Thanks for sharing this - I genuinely hadn't thought of just looping with a short sleep, but this new approach, combined with understanding now static vs non-static has been extremely useful

It has also allowed me to add additional functionality into the loop itself

Create an account or sign in to comment

Recently Browsing 0

  • No registered users viewing this page.

Account

Navigation

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.