Jump to content
Einstein

Einstein's Scripting Tutorial - Part 2

Recommended Posts

Einstein's Scripting Tutorial

Part 2 - Intermediate Concepts

 

 

This tutorial was written for the intermediate scripters that are already familiar with the basics and know quite a bit of Java.

If you're just starting out, read the first part instead: https://tribot.org/forums/topic/74522-einsteins-scripting-tutorial-part-1/

 

In this second tutorial, we will briefly overview the following concepts:

  • Paint
  • GUI
  • Code structure
  • Anti-Ban
  • Concurrency

 

 

 

Paint

 

cmbIdL8.png

 

 

The graphical overlay that is displayed when running most scripts is commonly referred to as the script's 'paint'.

In order to draw the paint on the screen, your Script subclass (the class that extends Script) must implement the Painting interface.

Rxc2ryV.png

 

The onPaint method's thread runs concurrently (at the same time) with the main thread (the run method runs in the main thread). Running threads will be explained in more detail in the 'concurrency' section.

So this method runs independently from the rest of your script and it's invoked several times per second. In order to draw graphics on the screen, you will use the Graphics object that is passed as an argument (g in the above code).

For instance, let's cache two images into variables, then display them on the screen.

p0EQvJR.png

MMXuxYN.png

The above code will display the text "Drawing a String" at screen coordinates 0, 30 and will draw an image at 0, 0, which is exactly the top left corner.

 

In order to determine which coordinates to enter, you can select this from the client's menu bar. After doing so, the cursor's location will be displayed on the screen allowing you to determine the coordinates of the point in which you want to draw the graphics.

1PxqEYR.png

 

 

 

GUI

 

dCzHL3Q.png

 

GUI stands for Graphical User Interface, and it's usually displayed when the script starts.

Having a GUI can be very useful, because it allows your users to configure some settings, thus altering the script's behavior.

 

How to implement a Swing GUI into your script:

 

1. Make a JFrame

  • Create a new class that extends JFrame
  • This class will contain all the code that makes up the GUI: buttons, labels, check boxes and all other components

QYO0HTz.png

 

 

2. Instantiate the JFrame at the script's startup

  • Instantiate the class that you've previously created
  • Make sure that you enable its visibility
  • Make the code wait until the user closes the GUI. Script's execution will resume afterwards.

7Irum0P.png

 

The user is supposed to configure the GUI. After clicking start, all the settings should be programmatically stored in your script's variables, and the GUI should be disposed, which will allow the above code to resume execution, with the newly updated variables.

 

Note #1: when writing the code that disposes the GUI, do not call System.exit(), as this will terminate the whole JVM instance. Use the dispose() method instead.

Note #2 : Creating a GUI by hand can be tedious and error prone. Using an automated GUI builder, such as NetBeans is highly recommended.

 

 

 

 

 

Code Structure

 

Code structure refers to the way in which you organize your code.

If you're writing a basic script that consists of merely a few hundred lines of code, everything can be contained within a single class, and control flow can be easily manipulated using a simple binary decision tree:

 

fQvH7F6.png

 

 

However, if you are planning to write something more complex, you will need a better code structure that will allow you to organize your classes as neatly as possible. This doesn't serve for aesthetic purposes only, and has the following advantages:

  • Easier to detect bugs and logic errors
  • Easier to modify code
  • Easier to implement new features
  • If someone else is reading your code, they will understand it much faster

 

However, the importance of having a solid code structure is directly proportional with the complexity of your script. Which means that basic scripts don't really need an over engineered structure, while complex scripts will become almost impossible to create and maintain in the absence of one.

 

One of the most popular and successful code structures is the "Task" or "Node" framework. It can be implemented in many different ways, but the basic idea remains the same:

  • Script's actions are split into different classes that either subclass/implement a "Task" class/interface.
  • Those classes are instantiated and stored in an array or collection.
  • You iterate over the collection of Tasks, checking if any Task is "active" - i.e. the script needs to execute that task.

 

I wouldn't recommend using any other code structure other than this one. It's easy to understand and use and the code ends up very well organized. You can create your own implementation of this framework, and I suggest adding task prioritization, as this will further make the code even cleaner, as many redundant computations will no longer be required.

Lastly, I will link you to a comprehensive tutorial on how to use one of the variations of this framework: https://tribot.org/forums/topic/20101-node-framework-tutorial-increase-efficiency-and-clarity/

 

 

 

 

 

Anti-Ban

 

The anti-ban refers to the system implemented into a script, whose goal is to prevent its detection. Unfortunately, there is a lot of misinformation on this subject.

 

1. TRiBot's default AntiBan

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

Leave this as it is, do not attempt to disable it in any way, because thread manipulation is unsafe and can result in the client malfunctioning as a whole. The only reason for the AI Anti-Ban being included in this section, is so that you are aware of its existence.

 


2. Anti-Ban Compliance Utility v2

Commonly referred to as ABC2, this is based upon real human playing data that has been collected and analyzed. It's a powerful tool, and every aspiring scripter should at least understand how it works.

It's split into 4 different sections, which are working differently.

  • Timed actions - Performed while the player is waiting for an event to occur in the game.
    • Checking game tabs
    • Checking XP
    • Examining random entity
    • Mouse leaving the game window
    • Moving mouse
    • Simulating the player picking up the mouse
    • Right clicking
    • Rotating camera
  • Preferences - Preferred ways of doing certain actions in game
    • Preferred way to open the bank: Banker / Booth
    • Preferred way to switch game tabs: Mouse / Keyboard
    • Preferred way to walk to the destination: Use screen / minimap
    • Get the preferred next target to click
  • Action Conditions - if and when certain things will be done by the script
    • At what HP should the script eat
    • At what energy level should the script activate run
    • If and when should the script walk towards the next anticipated target (place where the target will spawn)
    • If and when should the script switch targets due to the high competition
    • If and when should the script hover over the next target
    • If and when should the script open the menu for the next target
  • Reaction times - How much should the script sleep before starting the next action
    • Generating the reaction time based on 9 different factors
    • Generate supporting tracker information for the reaction time generator
    • Actually sleeping the generated reaction time, before proceeding to the next action

 

Every RS account that runs a script implementing ABC2, will have their own unique profile, which means that the same code will run slightly differently on each individual account.

Here is the link to the official ABC2 implementing guide. Everything that you need to know about this utility is explained in this thread and in the links contained within it: https://tribot.org/forums/topic/60720-guide-to-implementing-abc2/

 

 

3. Your custom anti-ban

Don't even think about trying to implement your own custom anti-ban, because if you don't know exactly what you're doing, you will most likely increase the frequency of bans for your users.

As a beginner scripter, your best "anti-ban" is learning to write robust code, that is able to handle unexpected events and avoids getting stuck. Your script must be fully dynamic, and react to the game environment.

Most API methods return a boolean value that indicate what they have managed or failed to achieve. This value should be used to determine the script's next action: should it proceed to the next point, or should it re-try doing the same action.

 

 

 

 

 

Concurrency

 

Two threads are said to be concurrent if they run at the same time.

Although concurrency can be very useful, multiple threads having access to the same data (which they can read / modify) can lead to problems. There is a whole lesson on this subject, written by Oracle. Every scripter should at least understand the fundamental concepts: https://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

 

Concurrency issues among TRiBot scripts are very rare, to non-existent, especially with basic scripts. However, all scripters should know the basics in order to understand how a script is run and to identify potential concurrency problems.

The code written by the scripter inside the run method (overridden from the Script class) and all the other methods invoked from this method, directly or indirectly, are running in the same thread, which is commonly referred to as the "main" thread. Although the application has a completely different main thread, from the scripters perspective, this is the main thread where your code starts getting executed. When control flow exits this thread, the script ends.

As a rule of thumb, all code that results in mouse movement or key stokes must only be written in the main thread. All other threads should only update data, and the main thread will make decisions based upon this data. The methods implemented from interfaces such as Painting or MessageListening07 are running in their own threads (other than the main one), and the scripter should be aware of this.

 

 

 

 

 

The End

 

If you're striving to become a better scripter, learning more Java will always be a good idea. Here are some useful links:

 

Lastly, here is a link to the TRiBot API, an indispensable tool for scripters. If you haven't already bookmarked it, I strongly suggest doing it, as you will need to consult it very frequently during your scripting sessions: https://tribot.org/doc/

 

 

Thank you for reading the second part of my scripting tutorial, I hope you've enjoyed it and you're on the path of becoming a (better) scripter!

 

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 1

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
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:

      Add LG support for Runelite


      Fix NPCChat issues


      Fix a bug where the camera angle setter would just hold down a key for 5 seconds (the timeout)


      Slightly adjust the rotation via keys to be more accurate


      Add the ability for asynchronous camera movement via keys


      Make Camera rotation via mouse more fluid, with more antiban, and work much better in resizable mode


      Add a "Camera#setCamera" method, allowing the rotation and angle to be set in parallel


      Increase the likelihood of using the mouse for camera movements


      Add support for adjusting the camera to positionable entities (Positionable#adjustCameraTo)



      Upcoming updates:

      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
      • 30 replies
    • This update will:

      Allow for clicking through the chat box when possible (Thanks @Todd)


      Fix Combat#selectIndex (Thanks @Encoded)


      Ensure worlds stay sorted and added a check to avoid misclicks in the in-game world hopper (Thanks @erickho123)


      Fix out-dated Options API interface indices (Thanks @Todd)



      Upcoming updates:

      Break handler bug fix


      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
      • 12 replies
    • This release will:

      Fix login bot after today's game update (Thanks @JoeDezzy1)


      Fix latest in-game world hopping issues (Thanks @erickho123)


      Compact Settings UI and set location relative to TRiBot (Thanks @JoeDezzy1)


      Fix an older implementation of GrandExchange#getWindowState (Thanks @JoeDezzy1)


      Improve the preformance of NPCChat by only searching in certain interface parents (Thanks @JoeDezzy1)



      Upcoming updates:

      Break handler bug fix


      Improved CLI support


      LG support for RuneLite


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
      • 16 replies
    • This release will:

      Fix bytecode manipulation in order to prevent the modification of parameters within the Filter and Condition classes themselves (thanks @wastedbro)


      Fix NPE caused by non-null value in GE API (thanks @erickho123)


      Add and fix equals methods for api2007.types (thanks @JoeDezzy1)


      Modify Mouse#leaveGame to make the mouse leave the game from top, left, right, or bottom (thanks @erickho123)


      Add Entrana area to Ships API (thanks @erickho123)


      Fix raid prayers index/settings in Prayer API (thanks @erickho123)



      Upcoming updates:

      Break handler bug fix


      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
      • 29 replies
    • This update will:

      Implement better canvas locking/synchronization mechanism


      Fix small Login API bug


      Remove the requirement for xbooting Java classes


      Use ExecutorService to perform canvas work in parallel


      Add "Account Management" game tab to GameTab API (thanks @Encoded)


      Fix NPCChat#getMessage (thanks @Encoded )


      Fix NPCChat#selectOption (thanks @Encoded )


      Fix Banking API after today's update (thanks @Encoded )


      Fix in-game world hopper after today's update (thanks @Encoded )



      Upcoming updates:

      Break handler bug fix


      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
      • 38 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×