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 create a new thread?

Featured Replies

I need to create a new thread to keep watching the player's hitpoints. I looked for some tutorials here on the forum, but none worked, could someone help me please?.

I tried this:

        Event customEvent = new Event() {
            @Override
            public int execute() throws InterruptedException {
                return 0;
            }
        };
        customEvent.setAsync();
        execute(customEvent);

But it returns a lot of errors:
"Method does not override method from its superclass"
"Cannot resolve method 'setAsync' in 'Event'"

I much prefer to create a class that implements the runnable interface. This way it makes it much cleaner (at least imo).

Here is an example for my V2 slayer cannon shot listener.

private Thread cannonThread;
private CannonListener cannonListener;

 

public void startCannonListener() {
    cannonListener = new CannonListener(this);
    cannonThread = new Thread(cannonListener);
    cannonThread.start();
}

and the CannonListener class

public class CannonListener implements Runnable {

    private final Main script;

    private int shots = 0;
    private final ArrayList<Integer> loopList = new ArrayList<Integer>();

    public CannonListener(final Main script) {
        this.script = script;
    }

    @Override
    public void run() {
        script.log("Starting cannon listener...");
        while (script.getBot().getScriptExecutor().isRunning() || script.getBot().getScriptExecutor().isPaused()) {
            if (script.getClassProvider().getFighting().getCombatMaintenance().hasPlacedCannon()) {
                final List<Projectile> list = script.getProjectiles().filter(f -> f.getId() == 53);
                for (Projectile proj : list) {
                    if (!loopList.contains(proj.getLoopCycle())) {
                        shots += 1;
                        loopList.add(proj.getLoopCycle());
                    }
                }
            }
            Timing.waitCondition(() -> false, 100);
        }
    }

    public int getShots() {
        return shots;
    }

    public void resetShots() {
        this.shots = 0;
    }
}

Edited by Malcolm

On 10/7/2021 at 10:40 PM, Malcolm said:

I much prefer to create a class that implements the runnable interface. This way it makes it much cleaner (at least imo).

Here is an example for my V2 slayer cannon shot listener.

private Thread cannonThread;
private CannonListener cannonListener;

 

public void startCannonListener() {
    cannonListener = new CannonListener(this);
    cannonThread = new Thread(cannonListener);
    cannonThread.start();
}

and the CannonListener class

public class CannonListener implements Runnable {

    private final Main script;

    private int shots = 0;
    private final ArrayList<Integer> loopList = new ArrayList<Integer>();

    public CannonListener(final Main script) {
        this.script = script;
    }

    @Override
    public void run() {
        script.log("Starting cannon listener...");
        while (script.getBot().getScriptExecutor().isRunning() || script.getBot().getScriptExecutor().isPaused()) {
            if (script.getClassProvider().getFighting().getCombatMaintenance().hasPlacedCannon()) {
                final List<Projectile> list = script.getProjectiles().filter(f -> f.getId() == 53);
                for (Projectile proj : list) {
                    if (!loopList.contains(proj.getLoopCycle())) {
                        shots += 1;
                        loopList.add(proj.getLoopCycle());
                    }
                }
            }
            Timing.waitCondition(() -> false, 100);
        }
    }

    public int getShots() {
        return shots;
    }

    public void resetShots() {
        this.shots = 0;
    }
}

This is not thread safe. You need to guard access to 'shots'.

56 minutes ago, dreameo said:

This is not thread safe. You need to guard access to 'shots'.

48 minutes ago, Malcolm said:

It's perfectly safe for my usage. :doge:

 

Turn shots variable into an AtomicInteger :doge: 

and make sure the shots += 1 is incremented atomically (incrementing an int = multiple instruction sets: iinc and store?)

6 hours ago, Czar said:

 

Turn shots variable into an AtomicInteger :doge: 

and make sure the shots += 1 is incremented atomically (incrementing an int = multiple instruction sets: iinc and store?)

That would make it thread safe but programming logic would still be incorrect.

You wouldn't want to reset the 'shots' counter while you're iterating over the 'projectiles list'.  You would want to wait until that loop is finished and then allow the reset.

7 hours ago, Malcolm said:

It's perfectly safe for my usage. :doge:

 

Quote

If multiple threads access the same mutable state variable without appropriate synchronization, your program is broken

😄

  • Author
11 minutes ago, dreameo said:

 

😄

How would you make that same cannon code then?

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.