Skip 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.

[Open Source] Dubai's OakBurner [BETA]

Featured Replies

Dubai's OakBurner [BETA]

Chop and Burn any Oak Tree!

Start this script next to an Oak Tree with your axe equipped or in your inventory with a tinderbox.

The script will chop a full inventory of oak logs, and burn them before returning back to the starting tree.

(It might wander off while it's firemaking(It handles "You can't light a fire here" and moves to a new spot to keep lighting fires) But the script will return to the starting tree after burning.

Nice and simple Onscreen Paint tracking Runtime and XP/LVLs gained.


Oak-Burner10minutes.png

 

Need some testers on this, I've ran for over an hour without issues, just moving on to other things. If you encounter bugs/crashes please try and screenshot the issue and provide as much info as you can and I'll return to this project for fixes. I've been running it south/west falador and it works really well over 20k FM xp/hr depending on your axe. The bot seems really smooth, especially firemaking.

 

DOWNLOAD: (EXTRACT TO YOUR "OSBOT/SCRIPTS/" PATH)

If anyone could upload some screenshots of nice runtimes, that would be awesome!

Source:

Spoiler
import org.osbot.rs07.api.map.Position;
import org.osbot.rs07.api.model.Entity;
import org.osbot.rs07.api.ui.Skill;
import org.osbot.rs07.canvas.paint.Painter;
import org.osbot.rs07.listener.MessageListener;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;
import org.osbot.rs07.utility.ConditionalSleep;
import org.osbot.rs07.api.ui.Message;
import java.util.HashSet;
import java.util.Set;
import java.awt.*;

    @ScriptManifest(author = "Dubai", info = "Burn any oak tree!", name = "OakBurner", version = 1, logo = "")
    public class OakBurner extends Script implements MessageListener, Painter {

        private static final int OAK_TREE_ID = 10820;
        private boolean fireLit = false;
        private int moveRetryCount = 0;
        private static final int MAX_RETRY_COUNT = 3;

        // Paint-related variables
        private long startTime;
        private int startingWoodcuttingLevel;
        private int startingFiremakingLevel;
        private int startingWoodcuttingXP;
        private int startingFiremakingXP;
        private boolean shouldMoveToSafeSpot = false;

        private Position startingPosition; // Save the starting position

        private enum State {
            CHOPPING, LIGHTING_FIRES, MOVING_TO_SAFE_SPOT, RETURNING_TO_START
        }

        private State currentState = State.CHOPPING;

        @Override
        public void onStart() {
            getBot().addMessageListener(this);

            // Save the starting position
            startingPosition = myPosition();

            // Initialize paint-related variables
            startTime = System.currentTimeMillis();
            startingWoodcuttingLevel = skills.getStatic(Skill.WOODCUTTING);
            startingFiremakingLevel = skills.getStatic(Skill.FIREMAKING);
            startingWoodcuttingXP = skills.getExperience(Skill.WOODCUTTING);
            startingFiremakingXP = skills.getExperience(Skill.FIREMAKING);
        }

        @Override
        public void onExit() {
            getBot().removeMessageListener(this);
        }

        @Override
        public int onLoop() throws InterruptedException {
            log("Current State: " + currentState);

            switch (currentState) {
                case CHOPPING:
                    chopOakTree();
                    break;
                case LIGHTING_FIRES:
                    lightFires();
                    break;
                case MOVING_TO_SAFE_SPOT:
                    moveToSafeSpot();
                    break;
                case RETURNING_TO_START:
                    returnToStart();
                    break;
            }
            return random(200, 300);
        }

        private void chopOakTree() {
            log("State: CHOPPING");
            if (inventory.isFull()) {
                log("Inventory full, switching to LIGHTING_FIRES state.");
                currentState = State.LIGHTING_FIRES;
                return;
            }

            Entity oakTree = getObjects().closest(OAK_TREE_ID);
            if (oakTree != null && oakTree.interact("Chop down")) {
                log("Chopping Oak tree at: " + oakTree.getPosition());
                waitUntilNotAnimating();
                if (!inventory.isFull()) {
                    log("Finished chopping. Inventory not full. Retrying CHOPPING state.");
                    chopOakTree();  // Retry chopping if inventory isn't full
                } else {
                    log("Inventory full, switching to LIGHTING_FIRES state.");
                    currentState = State.LIGHTING_FIRES;
                }
            } else {
                log("No Oak tree found or failed to interact.");
            }
        }

        private void lightFires() throws InterruptedException {
            log("State: LIGHTING_FIRES");

            // Check if the bot should move based on the chat message
            if (shouldMoveToSafeSpot) {
                log("Should move to a safe spot due to chat message.");
                currentState = State.MOVING_TO_SAFE_SPOT;
                shouldMoveToSafeSpot = false;  // Reset the flag after setting the state
                return;
            }

            if (!inventory.contains("Oak logs")) {
                log("No Oak logs left. Switching to RETURNING_TO_START state.");
                currentState = State.RETURNING_TO_START;
                return;
            }

            if (inventory.contains("Tinderbox") && inventory.contains("Oak logs")) {
                log("Using Tinderbox on Oak logs.");
                if (inventory.getItem("Tinderbox").interact("Use")) {
                    new ConditionalSleep(1000) {
                        @Override
                        public boolean condition() {
                            return inventory.isItemSelected();
                        }
                    }.sleep();

                    if (inventory.isItemSelected()) {
                        if (inventory.getItem("Oak logs").interact("Use")) {
                            log("Using Oak logs.");
                            new ConditionalSleep(3000) {
                                @Override
                                public boolean condition() {
                                    return myPlayer().isAnimating();
                                }
                            }.sleep();

                            if (myPlayer().isAnimating()) {
                                log("Player is animating, waiting for fire to be lit.");
                                new ConditionalSleep(5000) {
                                    @Override
                                    public boolean condition() {
                                        return !myPlayer().isAnimating();
                                    }
                                }.sleep();

                                if (fireLit) {
                                    log("Fire lit successfully. Continuing to light more fires.");
                                    fireLit = false;
                                    lightFires();
                                } else if (shouldMoveToSafeSpot) {  // Double-check before retrying
                                    log("Detected 'You can't light a fire here.' while animating. Switching to MOVING_TO_SAFE_SPOT state.");
                                    currentState = State.MOVING_TO_SAFE_SPOT;
                                    shouldMoveToSafeSpot = false;
                                } else {
                                    log("Retrying lighting fires.");
                                    lightFires();
                                }
                            } else {
                                log("Failed to start lighting logs, retrying.");
                                lightFires();
                            }
                        } else {
                            log("Failed to interact with Oak logs.");
                        }
                    } else {
                        log("Failed to select Tinderbox.");
                    }
                } else {
                    log("Failed to use Tinderbox.");
                }
            } else {
                log("Tinderbox or Oak logs not found in inventory.");
            }
        }

        private Set<Position> attemptedSafeSpots = new HashSet<>();

        private void moveToSafeSpot() throws InterruptedException {
            log("State: MOVING_TO_SAFE_SPOT");
            Position safeSpot = findSafeSpot(3, 6);
            if (safeSpot == null || safeSpot.equals(myPosition())) {
                log("No suitable safe spot found. Expanding search area.");
                safeSpot = findSafeSpot(6, 10);
            }

            if (safeSpot != null && !safeSpot.equals(myPosition())) {
                log("Moving to safe spot at: " + safeSpot);
                attemptedSafeSpots.add(safeSpot); // Add the safe spot to the attempted list
                if (getWalking().webWalk(safeSpot)) { // Use webWalk instead of walk
                    Position finalSafeSpot = safeSpot;
                    new ConditionalSleep(7000) {
                        @Override
                        public boolean condition() {
                            return myPlayer().getPosition().equals(finalSafeSpot);
                        }
                    }.sleep();
                    if (myPlayer().getPosition().equals(finalSafeSpot)) {
                        log("Arrived at the safe spot. Switching to LIGHTING_FIRES state.");
                        currentState = State.LIGHTING_FIRES;
                        moveRetryCount = 0;
                        lightFires(); // Call the lightFires method to start lighting fires again
                    } else {
                        log("Failed to reach the safe spot. Retrying.");
                        retryMovement();
                    }
                } else {
                    log("Failed to initiate webWalk. Retrying.");
                    retryMovement();
                }
            } else {
                log("Failed to find a safe spot. Retrying.");
                retryMovement();
            }
        }

        private void retryMovement() throws InterruptedException {
            log("Failed to move to the safe spot. Retrying.");
            moveRetryCount++;
            if (moveRetryCount >= MAX_RETRY_COUNT) {
                log("Max retry count reached, returning to starting location.");
                currentState = State.RETURNING_TO_START;
                moveRetryCount = 0;
            } else {
                moveToSafeSpot();
            }
        }

        private void waitUntilNotAnimating() {
            new ConditionalSleep(5000) {
                @Override
                public boolean condition() {
                    return !myPlayer().isAnimating();
                }
            }.sleep();
        }

        private boolean useItem(String itemName) {
            return inventory.getItem(itemName).interact("Use");
        }

        private Position getSafeSpot() {
            return findSafeSpot(3, 6);
        }

        private Position getSafeSpotFarther() {
            return findSafeSpot(6, 10);
        }

        private Position findSafeSpot(int minRadius, int maxRadius) {
            for (int radius = minRadius; radius <= maxRadius; radius++) {
                for (int x = -radius; x <= radius; x++) {
                    for (int y = -radius; y <= radius; y++) {
                        Position pos = myPosition().translate(x, y);
                        if (!pos.equals(myPosition()) && getMap().canReach(pos) && !isFireNearby(pos) && !attemptedSafeSpots.contains(pos)) {
                            log("Found safe spot: " + pos);
                            return pos;
                        }
                    }
                }
            }
            log("No safe spot found within radius.");
            return null;
        }

        private boolean isFireNearby(Position pos) {
            return getObjects().closest(obj -> obj != null && obj.getName().equals("Fire") && obj.getPosition().equals(pos)) != null;
        }

        private void returnToStart() {
            log("State: RETURNING_TO_START");
            if (getWalking().webWalk(startingPosition)) {
                new ConditionalSleep(7000) {
                    @Override
                    public boolean condition() {
                        return myPlayer().getPosition().equals(startingPosition);
                    }
                }.sleep();
                if (myPlayer().getPosition().equals(startingPosition)) {
                    log("Returned to starting position. Switching to CHOPPING state.");
                    currentState = State.CHOPPING;
                } else {
                    log("Failed to return to starting position. Retrying.");
                    retryReturnToStart();
                }
            } else {
                log("Failed to initiate webWalk to starting position. Retrying.");
                retryReturnToStart();
            }
        }

        private void retryReturnToStart() {
            log("Retrying return to starting position.");
            moveRetryCount++;
            if (moveRetryCount >= MAX_RETRY_COUNT) {
                log("Max retry count reached. Switching to CHOPPING state.");
                currentState = State.CHOPPING;
                moveRetryCount = 0;
            } else {
                returnToStart();
            }
        }

        @Override
        public void onMessage(Message message) throws InterruptedException {
            log("Received message: " + message.getMessage());
            if (message.getType() == Message.MessageType.GAME) {
                if (message.getMessage().contains("The fire catches and the logs begin to burn.") ||
                        message.getMessage().matches(".*logs begin to burn.*")) {
                    log("Detected fire lit message.");
                    fireLit = true;
                } else if (message.getMessage().contains("You can't light a fire here.")) {
                    log("Detected 'You can't light a fire here.' message.");
                    shouldMoveToSafeSpot = true;  // Set the flag to indicate movement is needed
                }
            }
        }

        @Override
        public void onPaint(Graphics2D g) {
            long runTime = System.currentTimeMillis() - startTime;

            int currentWoodcuttingLevel = skills.getStatic(Skill.WOODCUTTING);
            int currentFiremakingLevel = skills.getStatic(Skill.FIREMAKING);
            int woodcuttingXP = skills.getExperience(Skill.WOODCUTTING) - startingWoodcuttingXP;
            int firemakingXP = skills.getExperience(Skill.FIREMAKING) - startingFiremakingXP;
            int xpPerHourWoodcutting = (int) (woodcuttingXP * 3600000D / runTime);
            int xpPerHourFiremaking = (int) (firemakingXP * 3600000D / runTime);

            g.setColor(Color.WHITE);
            g.drawString("Runtime: " + formatTime(runTime), 10, 30);
            g.drawString("Woodcutting Level: " + currentWoodcuttingLevel + " (+" + (currentWoodcuttingLevel - startingWoodcuttingLevel) + ")", 10, 45);
            g.drawString("Firemaking Level: " + currentFiremakingLevel + " (+" + (currentFiremakingLevel - startingFiremakingLevel) + ")", 10, 60);
            g.drawString("Woodcutting XP/Hour: " + xpPerHourWoodcutting, 10, 75);
            g.drawString("Firemaking XP/Hour: " + xpPerHourFiremaking, 10, 90);
        }

        private String formatTime(long ms) {
            long totalSeconds = ms / 1000;
            long hours = totalSeconds / 3600;
            long minutes = (totalSeconds % 3600) / 60;
            long seconds = totalSeconds % 60;
            return String.format("%02d:%02d:%02d", hours, minutes, seconds);
        }
    }

 

Edited by dubai

  • dubai changed the title to [Open Source] Dubai's OakBurner [BETA]

Wow, you're on fire with these releases... Literally with this one! Had a quick glance over it, looks good!

  • Author
43 minutes ago, Fanny said:

Wow, you're on fire with these releases... Literally with this one! Had a quick glance over it, looks good!

Very punny response, thank you <3

These 2 open source projects were some of my early projects, still fun and they do work nicely.

Edited by dubai

  • 5 months later...

Create an account or sign in to comment

Recently Browsing 0

  • No registered users viewing this page.

Account

Navigation

Search

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.