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.

How to recheck the state of an RS2Object? (check if rock has been mined)

Featured Replies

So I've been building a mining script and want a way to check if the rock being mined still exists whilst the player is mining it, say for instance another player manages to mine it before I do and then I can make the bot stop the mining animation and find another rock that has ore it and start mining that.

This is my mining function: 

private void mine(String chosenOre) {
        // Get rock to mine
        RS2Object rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object));

        if (!playerAnimating()) { // Check if player is not animating
            if (rockToMine != null) { // Check if rock is not null
                if (rockToMine.interact("Mine")) { 
                    new ConditionalSleep(1000, 500) {
                        @Override
                        public boolean condition() throws InterruptedException {
                            return playerAnimating();
                        }
                    }.sleep();
                }
            }
        }
    }

What would be the best way to implement the check for if the rock being mined still exists? I have tried putting within the return of  the ConditionalSleep return rockToMine != null as  a check but I didnt work, which I am assuming is due to the state of the rock being checked, being the original one from when it had ore in at and not the updated state of the rock that is empty? If so how do you get the updated state of the currently selected object, to then check its current state?

Thanks in advance for any help.

  • Author

Thanks for the reply, I have actually being using that Explv's code snippet already in this script. So I changed my code to the following:

    private void mine(String chosenOre) {
        // Get rock to mine
        RS2Object rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object));

        if (!playerAnimating()) { // Check if player is not animating
            if (rockToMine != null) { // Check if rock is not null
                if (rockToMine.interact("Mine")) {
                    new ConditionalSleep(3000, 500) {
                        @Override
                        public boolean condition() throws InterruptedException {
                            return Rock.CLAY.hasOre(rockToMine) && myPlayer().isAnimating();
                        }
                    }.sleep();
                }
            }
        }
    }

So in the conditional sleep's return I added the the hasOre check to the currently being mined ore, but it doesnt seem to be making a difference, if the rock gets mined by someone else, it just runs the full length of the animation and then tries to select another rock again.

26 minutes ago, sombotdude said:

if the rock gets mined by someone else, it just runs the full length of the animation

So solve this. You know your player is going to keep animating if the rock is mined out, so maybe your condition shouldn't be relying solely on the player's animation?

1 hour ago, sombotdude said:

Thanks for the reply, I have actually being using that Explv's code snippet already in this script. So I changed my code to the following:


    private void mine(String chosenOre) {
        // Get rock to mine
        RS2Object rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object));

        if (!playerAnimating()) { // Check if player is not animating
            if (rockToMine != null) { // Check if rock is not null
                if (rockToMine.interact("Mine")) {
                    new ConditionalSleep(3000, 500) {
                        @Override
                        public boolean condition() throws InterruptedException {
                            return Rock.CLAY.hasOre(rockToMine) && myPlayer().isAnimating();
                        }
                    }.sleep();
                }
            }
        }
    }

So in the conditional sleep's return I added the the hasOre check to the currently being mined ore, but it doesnt seem to be making a difference, if the rock gets mined by someone else, it just runs the full length of the animation and then tries to select another rock again.


Currently you only mine a new rock if your player isn't animating, so of course it will wait for the animation to complete. You should try doing something like this instead:

 

private RS2Object rock = null;

@Override
public int onLoop() throws InterruptedException {
    // If we haven't looked for a rock yet, or the player isn't animating, or the current rock no longer has Clay
    if (rock == null || !myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock)) {
        // Find a new rock
        rock = getObjects().closest(object -> Rock.CLAY.hasOre(object));
        // If a rock exists, and we successfully interact with it
        if (rock != null && rock.interact("Mine")) {
            new ConditionalSleep(3000, 500) { // Sleep for 3 seconds or until...
                @Override
                public boolean condition() throws InterruptedException {
                    // The player is animating, or someone else mined the rock
                    return myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock);
                }
            }.sleep();
        }
    }
}

 

  • Author
47 minutes ago, NoxMerc said:

So solve this. You know your player is going to keep animating if the rock is mined out, so maybe your condition shouldn't be relying solely on the player's animation?

Yep that's what I thought and was trying to implement with this: 

new ConditionalSleep(3000, 500) {
                        @Override
                        public boolean condition() throws InterruptedException {
                            return Rock.CLAY.hasOre(rockToMine) && myPlayer().isAnimating();
                        }
                    }.sleep();

But it still just resulted in the mining animation playing for its full length in almost all cases.

Of course, because that's going to break out of the conditional sleep (after 3 seconds or the clay is mined), return to the top of your loop, see that your player is animating, continue.

 

  • Author
41 minutes ago, Explv said:


Currently you only mine a new rock if your player isn't animating, so of course it will wait for the animation to complete. You should try doing something like this instead:

 


private RS2Object rock = null;

@Override
public int onLoop() throws InterruptedException {
    // If we haven't looked for a rock yet, or the player isn't animating, or the current rock no longer has Clay
    if (rock == null || !myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock)) {
        // Find a new rock
        rock = getObjects().closest(object -> Rock.CLAY.hasOre(object));
        // If a rock exists, and we successfully interact with it
        if (rock != null && rock.interact("Mine")) {
            new ConditionalSleep(3000, 500) { // Sleep for 3 seconds or until...
                @Override
                public boolean condition() throws InterruptedException {
                    // The player is animating, or someone else mined the rock
                    return myPlayer().isAnimating() || !Rock.CLAY.hasOre(rock);
                }
            }.sleep();
        }
    }
}

 

Thanks for the reply, ahh right I see now what I was doing wrong and this looks exactly like what I should be doing. But even using that code it still continues the animation if someone else has mined the rock before my player. I added some extra code to try and get a better understand of what was going on: 

if (rockToMine == null || !myPlayer().isAnimating() || !Rock.CLAY.hasOre(rockToMine)) {
            rockToMine = getObjects().closest(object -> Rock.CLAY.hasOre(object));
            if (rockToMine != null && rockToMine.interact("Mine")) {
                new ConditionalSleep(3000, 1000) {
                    @Override
                    public boolean condition() throws InterruptedException {
                        if (!Rock.CLAY.hasOre(rockToMine)) {
                            log("Rock has no ore!");
                            return true;
                        } else if (!myPlayer().isAnimating()) {
                            log("Animation finished!");
                            return true;
                        } else {
                            return false;
                        }
                    }
                }.sleep();
            }
        }

When checking the log, the "Rock has no ore!" never appears, which is confusing as I have watched the bot in times when the rock is empty of ore and the animation is still continuing regardless, it never reaches the "Rock has no ore!" output, just only ever outputting "Animation finished", whenever the animation has finished.

I also changed the sleep conditional return to myPlayer().isAnimating() to !myPlayer().isAnimating()  as wouldn't I want it to return true if the player had stopped animating, to break the sleep conditional? 

Two things.

The biggest sin you're committing is that you're acquiring an RS2Object, storing it in a variable, and then waiting for one of its properties (modifiedColors) to magically change. Do you see the issue here?

The other is that clay respawns relatively quickly. You're checking once every second if the rock (with the magically-updating fields??) doesn't have ore, but what if clay always has ore between one-second intervals?

Look at using the stored rocks position and writing a condition that finds the same rock on that position and checks if it doesn’t have ore, rather than checking the referenced rock. 

private boolean checkRockHasOreAtPosition(Position p){

    RS2Object rock = getObjects().getAll()
      .stream()
      .filter(obj -> obj.getPosition().equals(p) && Rock.CLAY.hasOre(obj))
      .findFirst()
      .orElse(null);

    return rock != null;

}

Something like that 

Edited by jca

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.