Jump to content
Einstein

Einstein's Scripting Tutorial Part 2

Recommended Posts

Einstein's Scripting Tutorial [Part 2]

 

Target audience: Beginners

Level of expertise: Doesn't try to download RAM

Estimated duration: 20 minutes

 

The first tutorial focused on how to get a script started; the very basics.

The part 2 will focus on slightly more advanced topics such as:

  1. Paint
  2. Graphical User Interface
  3. Code structure
  4. Anti Ban
  5. Script arguments
  6. Debugging
  7. Concurrency

Let's get started!

 

1. Paint

In order to add a paint to your script, you need to make the main class implement the Painting interface.

qDXjDPO.png

Nice! Now you can use the g object to draw images and text on the screen.

Let's use the getImage() method to cache two images. One stored on the computer and one from the web.

As always, use your IDE's keyboard shortcut to handle imports. (Eclipse users: Ctrl + Shift + O)

p0EQvJR.png

Notes:

  • https://imgur.com/ offers free and reliable image hosting.
  • file:// is the prefix for the file protocol, the extra / points to the root directory of the current drive.

 

Using the g object to draw a string and an image:

MMXuxYN.png

The string will now displayed at the specified screen location, in the top left corner.

In order to accurately determine the coordinates you need to use TRiBot's debugger:

1PxqEYR.png

 

 

2. Graphical User Interface

By adding a GUI you won't have to rewrite and re-compile the code every time you want to change the script's settings (for example: the name of the NPC a combat script will attack, or the type of tree a Woodcutting script will chop down).

1. You first need to create a class that extends JFrame.

QYO0HTz.png

 

2. Initialize the GUI. You can do this in the run() method, but I like to initialize the GUI and handle other script configurations in the onStart() method. (You will need to make your class implement Starting).

cy9IJGR.png

 

3. Implement an action listener: upon clicking "Start" on your GUI, cache all the settings in your variables class and dispose() the GUI.

Do not: use System.exit(0)

Do: setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE) or setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)

I highly recommend using NetBeans for fast designing and a professionally looking GUI.

 

 

 

3. Code Structure

Any kind of non-trivial script requires some sort of framework. Otherwise the code will become unmanageable very quickly.

 

A. Binary:

It looks something like this:7AgZNbt.png

 

 

 

 

B. Task/Node framework:

Basically the idea is this:

1. You have an abstract class or an interface called Node that defines two methods: shouldExecute() and execute().

2. All the script actions are split into different classes that inherit/implement the Node class/interface, therefore inheriting both methods.

  • shouldExecute() defines when the action should happen. For example consider a class called DropLogs. The shouldExecute() method will return TRUE if the inventory is full.
  • execute() method is the action itself. Using the same Woodcutting example, execute() will run the code that actually drops the logs.

3. Main class creates a Node object from each Node subclass, groups all the created objects in a list, and iterates through the list members with the following logic:

 if ( shouldExecute() returns TRUE )

  then execute();

 

A comprehensive guide on how to use the node framework:

 

 

 

 

C. State based script

soon™

 

 

 

 

 

4. Anti-Ban

A. TRiBot's AI Anti-Ban

TRiBot has an AI Anti-Ban that runs in the background and is enabled by default.

  • Script#getAIAntibanState() returns its current state (true by default)
  • Script#setAIAntibanState() enables or disables it. This method can only be used by users that have been granted the rank of Scripter.

 

Although this functionality can be disabled by manipulating threads, it's highly recommended to leave this default anti-ban enabled and do not interfere with it. According to TRiLeZ, attempting to use deprecated thread methods to disable this feature is "unsafe and can cause disastrous effects".

For those still interested in the code:

Spoiler

dW7r2yV.png

Note: After suspending the thread's execution, Script#getAIAntibanState will still return TRUE because its internal flag was never changed. However even if the returned value of that method suggests otherwise, the AI anti-ban is no longer executing.

 

 

B. ABC2

ABC2 is designed to use real human playing data instead of pseudo-randomization for deciding:

  If / When the bot should:

  • check xp
  • examine entity
  • move mouse
  • rotate camera
  • move to anticipated location etc.

When the bot should:

  • eat
  • activate run etc.

How the bot should:

  • open bank
  • open tabs
  • walk etc.

And how long the bot should wait before reacting to an event.

I can't explain it better than TRiLeZ, so here is the link to the official ABC2 implementing guide. https://tribot.org/forums/topic/60720-guide-to-implementing-abc2/

However, I would like to clarify one single aspect (has been asked many times / some users are confused):

ABC2: Anti-Ban Compliance utility version 2

ABCL: Anti-Ban Compliance Level, ranging from 0 to 10, based on a point system explained in the tutorial I linked above.

A script will either "have" both ABC2 and ABCL level 0-10, or it will "have" none of them.

 

C. Your custom anti-ban

The only thing I have to say is be careful.

Basing your custom anti-ban on a random number generator will most likely get you banned even faster. Humans are unable to perform random actions consistently. More information on this subject can be found here:   https://tribot.org/forums/topic/60719-tribot-release-9300_0-abc2/

 

 

 

 

5. Script arguments

A handy alternative to GUI.

In order to use script arguments, you need to implement the Arguments interface.

Su6vl6u.png

 

All arguments written in the bottom left box of the Script Manager will be passed to the overridden method in a form of a hash map. The script can then set variables based on the values of the hash map.

4xJpi1I.png

 

 

 

 

6. Debugging

Regardless of your level of expertise, bugs will remain a fact of life. Debugging your scripts can be done in multiple ways. One of the easiest ways is to print messages in the console as the code executes:

WYT4sDs.png

 

Methods that can be used to achieve this:

  • Script.println() - prints to the Client Debug
  • General.println() - prints to the Client Debug
  • System.out.println() - prints to the Bot Debug

5oCj3Pk.png

 

 

 

 

7.Concurrency

All methods from the interfaces implemented by your script will be concurrent (will run at the same time) with the main thread. Example of concurrent methods:

CR5g1xq.png

Ideally, you would want to have all in-game actions performed in the main thread.

All other threads should be used to manipulate data.

 

 

The end

Thank you for reading part II of my scripting tutorial.

I hope you enjoyed it and you learned something.

 

Edited by Einstein
  • Like 5

Share this post


Link to post
Share on other sites
3 minutes ago, Einstein said:

TzhaqAQ.png

A method named getX would assume a return value. Something more appropriate would be this.

 

private Thread getAntibanThread() {
	for (Thread t : Thread.getAllStackTraces().keySet())
		if (thread.getName().contains("Antiban))
			return t;

	return null;
}

antiBanThread = getAntibanThread();

 

  • Like 2

Share this post


Link to post
Share on other sites
Just now, Blastois3 said:

A method named getX would assume a return value. Something more appropriate would be this.

 

private Thread getAntibanThread() {
	for (Thread t : Thread.getAllStackTraces().keySet())
		if (thread.getName().contains("Antiban))
			return t;

	return null;
}

antiBanThread = getAntibanThread();

 

You're right.

Thanks!

Share this post


Link to post
Share on other sites
Just now, lets be friends said:

Good stuff. Wish you did more with the antiban instead of just linking to a thread but everything else was great.

Regarding ABC2 implementation, it simply can't be explained better than it already is in the official guide. Your best bet would be to check out some open source scripts that implement the utility.

 

I'm glad you liked the tutorial. :)

Share this post


Link to post
Share on other sites
2 minutes ago, lets be friends said:

Good stuff. Wish you did more with the antiban instead of just linking to a thread but everything else was great.

ABC2 tutorial by TRiLeZ, what more could you ask for :)

Thanks for taking the time to write this and spreading the (Tai Lopez voice) KNOWLEDGE. 

  • Haha 1

Share this post


Link to post
Share on other sites

Nice tutorial.

I find it funny how you use a control-flow diagram to illustrate your code structure. However, the Task/Node frameworks do not allow this type of structure. 

 

Your diagram illustrates a Binary Decision Tree of Decisions and Processes. I am cooking up a framework now that allows for that exact node structure! Stay tuned.

Share this post


Link to post
Share on other sites
5 minutes ago, YoHoJo said:

ABC2 tutorial by TRiLeZ, what more could you ask for :)

Thanks for taking the time to write this and spreading the (Tai Lopez voice) KNOWLEDGE. 

Thanks!

It's much easier to learn scripting when you have a MENTOR.

EhwMsFG.jpg

 

Just now, wastedbro said:

Nice tutorial.

I find it funny how you use a control-flow diagram to illustrate your code structure. However, the Task/Node frameworks do not allow this type of structure. 

 

Your diagram illustrates a Binary Decision Tree of Decisions and Processes. I am cooking up a framework now that allows for that exact node structure! Stay tuned.

Thanks!

Looking forward to seeing your new framework. :shy:

  • Haha 1

Share this post


Link to post
Share on other sites
12 minutes ago, wastedbro said:

Nice tutorial.

I find it funny how you use a control-flow diagram to illustrate your code structure. However, the Task/Node frameworks do not allow this type of structure. 

 

Your diagram illustrates a Binary Decision Tree of Decisions and Processes. I am cooking up a framework now that allows for that exact node structure! Stay tuned.

Can't edit the comment above.

Well, the diagram illustrates the binary tree (point A).

 

The node framework (point B) has no diagram, it's explained with text only. I've edited the thread and added spacing to prevent confusion. :lol:

Thanks for pointing it out!

  • Like 1

Share this post


Link to post
Share on other sites
On 26.11.2017 at 10:37 PM, Einstein said:

5. Script arguments

A handy alternative to GUI.

In order to use script arguments, you need to implement the Arguments interface.

Su6vl6u.png

 

All arguments written in the bottom left box of the Script Manager will be passed to the overridden method in a form of a hash map. The script can then set variables based on the values of the hash map.

4xJpi1I.png

 

wot m8?

Share this post


Link to post
Share on other sites
50 minutes ago, rstaiger said:

arguments like, do they change variables? or they are like a method

They change a variable.

The script you are using has to support arguments. Let's say you have a woodcutting script and you have 3 bots. One bot is just starting out so your argument for that client or script instance is PROGRESSIVE and you want it to POWERCHOP for example. The next two bots have high wc level so you could leave on PROGRESSIVE or have them cut a specific tree in a specific area and you want them to bank instead of powerchop and you want it to stop after 4 hours. So your argument might look like: YEW, WC_GUILD, BANK , 4.  You can save a profile under your script queue that has everything set up for you. All you need to do is start the queue. Similar for the client starter.

Share this post


Link to post
Share on other sites

Hey, Im writing my first TriBot script and I'm having some problems with my paint. I'm trying to draw the total amount of fish caught with a message listener.... However I don't know how to call on the listener if it becomes "true." What i tried doing was setting a Boolean to true whenever the message appears and then from there counting the amount of times it was set off. How would i go about doing this?

	@Override
	public void serverMessageReceived(String s) {
		if (s.contains("You catch some shrimps.")) {
			boolean caughtFish = true;
		}
		
	}
	
	@Override
	public void onPaint(Graphics g) {
		
		long timeRan = System.currentTimeMillis() - startTime;
		
		int currentLvl = Skills.getActualLevel(SKILLS.FISHING);
		int gainedLvl = (currentLvl - staticLvl); 
		int currentXP = Skills.getXP(SKILLS.FISHING);
		int gainedXP = (currentXP - staticXP);
		
		Graphics2D gg = (Graphics2D)g;
		gg.drawImage(img, 0, 304, null);
		
		g.setColor(new Color(8, 126, 253));
		g.setFont(font);
		
		g.drawString(Timing.msToString(timeRan), 358, 368);
		
		g.drawString(gainedXP + "", 358, 428);
		g.drawString("" + currentLvl, 458, 428);
		g.drawString("(" + gainedLvl + ")", 478, 428);
		
		if(caughtFish = true);
			g.drawString("**Ammount of fish caught**", 478, 398);
	
	}

 

Share this post


Link to post
Share on other sites
On 7/2/2018 at 2:09 AM, Pitbull Sc said:

I'm trying to draw the total amount of fish caught with a message listener.... However I don't know how to call on the listener if it becomes "true." What i tried doing was setting a Boolean to true whenever the message appears and then from there counting the amount of times it was set off

Simply declare an integer variable that will be incremented (++) every time you catch a new fish. Then in the paint method:

g.drawString(String.valueOf(integerVariable), x, y);

 

Share this post


Link to post
Share on other sites
Quote
9 hours ago, Einstein said:

Simply declare an integer variable that will be incremented (++) every time you catch a new fish. Then in the paint method:

 

Thanks for the response, however, what I tried doing is not working. I think the problem i'm having is that when I make the int variable it is local to the serverMessageRecieved method and I can't access it from the onPaint method. How can i access it?

	int zero = 0;
	@Override
	public void serverMessageReceived(String s) {
		if (s.contains("You catch some shrimps.")) {
				int totalFish = (++zero);
		}
		
	}

	@Override
	public void onPaint(Graphics g) {
		g.drawString(String.valueOf(totalFish) + "", 358, 398);
	}

 

  • Haha 1

Share this post


Link to post
Share on other sites
14 minutes ago, Pitbull Sc said:

Thanks for the response, however, what I tried doing is not working. I think the problem i'm having is that when I make the int variable it is local to the serverMessageRecieved method and I can't access it from the onPaint method. How can i access it?

	int zero = 0;
	@Override
	public void serverMessageReceived(String s) {
		if (s.contains("You catch some shrimps.")) {
				int totalFish = (++zero);
		}
		
	}

	@Override
	public void onPaint(Graphics g) {
		g.drawString(String.valueOf(totalFish) + "", 358, 398);
	}

 

You need to declare the int variable totalFish OUTSIDE of the message listener method, then just increment that variable by doing totalFish++;

  • Like 1

Share this post


Link to post
Share on other sites
Posted (edited)
16 minutes ago, Pitbull Sc said:

what I tried doing is not working. I think the problem i'm having is that when I make the int variable it is local to the serverMessageRecieved method and I can't access it from the onPaint method. How can i access it?

The int variable declared within that if block is destroyed after the first '}', you won't be able to access it outside its scope.

Instead of having it within that method, simply declare it as a field, like you did with the oddly named 'zero' variable. You don't need additional variables for this purpose. Just declare a single one that will be incremented in the listener, and drawn on the screen by onPaint().

DriIIK6.png

Edited by Einstein

Share this post


Link to post
Share on other sites

Been stuck for over an hour just trying to figure out why the painting script won't work on Tribot, continuously getting the error:

"Error: Main method not found in class scripts.TutorialClass, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application"

 

don't reall have any notes to add why that might be I am very lost.

package scripts;

import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;

import org.tribot.api.General;
import org.tribot.script.Script;
import org.tribot.script.interfaces.Painting;


public class TutorialClass extends Script implements Painting{
    @Override
    public void run() {
        while (true) {
       }
}

    @Override
    public void onPaint(Graphics g) {
                 
    }
    


private static Image getImage(String url) {
    try { 
        return ImageIO.read(new URL(url));
    } catch (IOException e) {
        General.println("Failed to load image!");
    
    }
    return null;
}
static final Image LOCAL_IMAGE = getImage ("file:///C:/Users/Jacob/Desktop/image.jpg");
static final Image WEB_IMAGE = getImage("https://i.imgur.com/nieQEiy.jpg");


public void OnPaint(Graphics g) {
    g.drawString("Drawing a String", 0, 30);
    g.drawImage(LOCAL_IMAGE, 0, 0, null);
}
}

 

Share this post


Link to post
Share on other sites
1 hour ago, SwagLordGuy said:

Been stuck for over an hour just trying to figure out why the painting script won't work on Tribot, continuously getting the error:

"Error: Main method not found in class scripts.TutorialClass, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application"

 

don't reall have any notes to add why that might be I am very lost.
 

  Reveal hidden contents

 

package scripts;

import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;

import org.tribot.api.General;
import org.tribot.script.Script;
import org.tribot.script.interfaces.Painting;


public class TutorialClass extends Script implements Painting{
    @Override
    public void run() {
        while (true) {
       }
}

    @Override
    public void onPaint(Graphics g) {
                 
    }
    


private static Image getImage(String url) {
    try { 
        return ImageIO.read(new URL(url));
    } catch (IOException e) {
        General.println("Failed to load image!");
    
    }
    return null;
}
static final Image LOCAL_IMAGE = getImage ("file:///C:/Users/Jacob/Desktop/image.jpg");
static final Image WEB_IMAGE = getImage("https://i.imgur.com/nieQEiy.jpg");


public void OnPaint(Graphics g) {
    g.drawString("Drawing a String", 0, 30);
    g.drawImage(LOCAL_IMAGE, 0, 0, null);
}
}

 

 

 

You need to be vip to run local scripts. 

Share this post


Link to post
Share on other sites
Posted (edited)
19 minutes ago, SwagLordGuy said:

Look above my post count

Odd. it shows you are VIP now but it didn't before. Let me check out the error again.

@SwagLordGuy Check your onPaint(Graphics g) method. You have two of them.

The one you need is onPaint not OnPaint. Copy everything to onPaint from OnPaint

Edited by Jerminater

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Our picks

    • This release will:

      Fix key event handling issue


      Fix other event handling issue


      Fix RSServer hook


      Update world hopper to have it use OCR, thanks to Todd


      Use proper disposal of old Graphics objects


      Reformat code


      Rearrange code


      Organize code imports


      Apply around 8000 automated code refactorings


      Make preparations for Java 9


      Fix 11 various bugs


      Add more reliable debugging support


      Fix mouseEntered/Exited event dispatching bug


      Fix minimap walking bug where it opens the map


      Fix broken hooks for today's game update
      • 87 replies
    • This update will:

      Fix GE inventory item positioning bug


      Fix broken object hooks
      • 27 replies
    • This release will:

      Fix some ClosedChannelException bug


      Fix bug in RSObject#getAllTiles


      Add game tab support for "Kourend Favour"
      • 15 replies
    • This release will:

      Fix Settings UI placement bug


      Fix game object location bug


      Fix small layout bug making the client shift up and down


      Fix client crashing bug where loading the client with a small display area will cause the client to crash


      Fix annoying Linux bug relating to painting events and peers


      Fix settings saving bug where settings are saved to disk more often than they should


      Fix RSInterface#isBeingDrawn bug affecting a limited amount of people


      Drop Java 1.7 bytecode version for 1.8


      Important: Since the downloadable RS client uses Java 7, it will no longer be compatible with Looking Glass. To make up for this, we will add support for using other clients such as RuneLite (at a later date).


      This change was necessary to allow us to use Java 8 syntax. It also paves the way for Java 9/10/11 support.
      • 40 replies
    • This update will:

      Fix the RSMenuNode bug which also fixes the bug with bank opening


      Fix the incorrect object positions bug


      Fix and re-enable the LG Objects API Accelerator


      Fix the RSObject#getAllTiles bug
      • 22 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×