Jump to content
Jerminater

Jerm's AIO Scripting Setup Tutorial

Recommended Posts

Posted (edited)

JERM's AIO Scripting Setup Tutorial

 

Introduction -

I got into Java in early June 2018. I have not really played much RuneScape lately but am very fascinated with how programming works. In scripting for OSRS, I have come to see it as a very good way to learn my way about Java, and object-oriented programming in general. I got annoyed and lost a few times a long the way and used several resources throughout this website, YouTube, and Google. Today I am putting together a tutorial that will hopefully alleviate some of the pains I went through in learning and get someone set up right away in their scripting Journey. Enjoy!

What this Tutorial is NOT:

If you are looking to set up your Tribot client to run scripts, or need help getting scripts from the repository, or anything not related to the writing of scripts. Go somewhere else!

Also, I do not teach how to write code here. At least, not very much. Java tutorials are for that.

What this Tutorial IS:

This script is an all-inclusive trip to your dream of developing scripts for Tribot in the simplest of ways possible. I won’t use too many big terms and will explain things in ways that everyone can understand! 😎

This tutorial is for learning how to get setup with tribot, and understand how everything works and is connected.

Also, understand that this tutorial is for people who do not know how to script in Tribot. I go over one of the hundreds of ways to script. After you understand the way I do things. My hope is that you can get scripts going and learn about ways that would be better for you. The initial hump to get over when starting is very steep, and I want to help you get over it. I also use some screenshots as a demonstration from one of my old scripts that is far outdated. The information is sound, but the logic may be buggy, and incorrect. 

Get ready for a long one…

Outline –

1.    Prior Knowledge

2.    Getting set up in Eclipse

3.    Understanding the API

4.    How Tribot runs scripts

5.    Framework

6.    Walkthrough a script

7.    Setting up a GUI

8.    Designing a GUI

9.    GUI Settings

10. Paint

11.  Anti-ban

12. Your own API

13. Debugging

14. Useful tools

15. Repository

16. Navigating the site

17. Good practices

18. Resources

1.  Prior Knowledge

 

     I.        First off, if you are not a VIP on Tribot, you should stop now and go purchase it. If you do not, you will not be able to run your own scripts!

 

   II.        If all these words are not familiar to you, or you do not know what they mean, you need to stop now and go learn what they are! It means you do not have enough knowledge to produce quality scripts on Tribot. You may be able to produce scripts that do something you want, but they will most likely be subpar. Your code will be messy, won’t prevent bans, and won’t be efficient. You really should have a working knowledge of Java prior to scripting for Tribot.

Words: Method, Interface, Extends, while loop, debug, class, package, bit, integer, string, array, array list.

 

 III.        If you skipped part 2 because you feel you are familiar enough with Java, there is a difference between being familiar with Java and knowing Java.

 

  IV.        In addition to this, please have a working knowledge of the Tribot client. Such as knowing how to run scripts, download scripts, mess around in the settings a little bit etc. This one you just need to be familiar with.

 

    V.        Remember how I said I learned Java less than a month ago? This is true. I did have some prior knowledge of another program called Matlab, but that’s about it. I took step 2 literally and did not script anything till about 2 weeks ago. Before this, I did hours of research, went through tens of Java tutorials, and read a book titled “Learn Java in 24 hours.” After doing so, I started scripting with enough knowledge to get the ball rolling. If I can do it, you can do it!

Okay now on to some more interesting stuff with pictures. I like pictures.

 

2.  Getting set up in Eclipse

Okay, before we can write any scripts, we need to download a few programs, and make sure a few settings/files are in the right order.

  1. Let’s go grab an IDE (Integrated development environment). If you have knowledge of Java, you should know what this is. I’ll explain the basics anyways. 

    An IDE is where you write you code. Done!

    Okay… an IDE is a bit more than that, but really, all you need to know is that you write your scripts in an IDE, and it will compile them (turn it from code you understand, to code the computer can understand and run). You can also organize all your scripts classes (bits of code in a file), and packages (folder that holds classes) in the IDE.

    Lastly, the IDE will help you in making sure your code is readable by Tribot by throwing errors at you, and will assist you in debugging errors.

    So, the IDE I like to use is Eclipse. There are several you could use such as NetBeans, or IntelliJ, but we will stick with this one. Select the Eclipse IDE for Java Developers. Make sure you download the bit size that matches your Tribot client for good measure. This is just a standard install. Do it however/wherever you please.


    Next download e(fx)clipse. This is needed for the GUI creation later.

    We also need SceneBuilder for our GUI later as well so grab that.

    Lastly, we will need something called allatori annotations. This is a .jar file that will help tribot in reading your GUI. The tribot repository scrambles all the names for your methods and fields to make it harder to hack into. In the .fxml file for the GUI these names are used, and they shouldn’t be scrambled. This .jar file will help prevent that later as well. Go ahead and place this .jar into the .tribot folder on your computer for ease of access. (Just type %AppData% into file explorer)


    6yFYIi4.png
     
  2. Now lets setup your eclipse for scripting.

    First off, enter eclipse. Select to the workbench in the top right if you need to, and create a new project. Make sure you select the .tribot directory for your project path! If you don’t do this, every time you make a change to your script, you will have to copy over the files to the .tribot/bin folder. This is very tedious. The project will create its own bin folder if you set the location here, and all you have to do is save your work and run your script!
    RDxLEVD.png

     *Ignore the error. It is there because I already made a Scripts folder.

    Next, right click your project>properties>Java Build Path>Libraries and add the two external Jars and the libraries shown. If previous steps were followed, they should all show up.

    YthENJf.png
    *The JRE library will depend on which one you installed when installing Java for running tribot


    Note: I use the Dark theme in Eclipse, if you want to use it just go to Window>Preferences>General>Appearance -> select Dark and Default (current) for the same theme I have. Other than this, I think all my settings are default!

    The dark theme makes it very easy to read the code in my opinion. I highly recommend it!

    This:
    qIunvLo.png
    vs.
    1Oc6eYE.png

    Notice how each part of a line is a different color? Makes it very easy to find things when the script gets larger.

3.  Understanding the API

Bookmark this. Right now. If you want to get serious into scripting, you need it.

This is the Tribot API (Application Programming Interface) and will be your best friend. The API contains all the methods, interfaces, classes etc. that you need to run any script for RuneScape. Your IDE, after following step 2, should have all these methods inside of it. To access them, you just need to import the specific portion of the API you want to access and use the method! Here, I’ll show you.

Notice how on the bottom left, you have something that looks like this:

UCFHNBm.png

This is the bread and butter. Do you need the script to do something in the bank? Click on “Banking.” (notice there are two. Click each one and see which one references RS3 and which one is for api2007:

AMTF9kM.png

Scroll down to “Method Summary.” Here is where you get your script to do things for you. Say I want my script to open the bank, deposit everything, then close it given I have something in my inventory. My code would look something like this:

ACLlyNL.png

*If you can’t understand this VERY simple algorithm, please refer to section 1 step 3.

As you can probably tell, the API is self-explanatory on what the methods mean!

Note: if the text is underlined in red, you can hover your mouse and import the needed files:

kOZQ7bX.png

*You can also hit ctrl+shift+O but it is quicker to just highlight.

To check return types of methods in the API, scroll down to “Method Detail” on the API page. Here you can see a description of the method, and a description of what type of information the method will return. Notice Banking.DepositAll() returns an integer that describes how many items were banked. Therefore my code checks to see if it is greater than 0 as an example.

Also, some of the methods are interfaces which need to be implemented into your script:

FPZXng5.png

I will assume you know what this means. (It means you must use the methods inherited from the class you implemented. lol) Ending is implemented, so my script must use onEnd():

Lw2g7s4.png

I could just leave it blank with no code if I don't want to use it. Useful for implementations that have several methods like MessageListening07:

KrIfuv3.png

That’s basically it with the API! It is all the methods you use to run your script, aside from the ones native to Java/other sources you use.

4.  How Tribot runs scripts

Take a look at this picture, we will go through it step by step:

nDPz72w.png

This is the skeleton of a script. Typically, your script will always look very similar to this at the start. To create this, you simply write the information in line 1, and 15-19. After this, everything will be underlined in red pretty much. Just import/create all the methods it requires, and you should get something like what I have above. It may just be in a different order. If you are missing a method, just type it like I have it above.

Okay, so this is the main class that governs your entire script. How it works is as follows:

  1. Your class extends “Script,” which basically just means it will work with tribot. This is what asked you to create the “run()” method earlier. When you hit start script, this is the method that runs. When complete, the script will end.
  2. If you implemented “Starting” the “onStart()” method is called first, and will typically hold all the algorithms you need the script to perform before actually doing anything. These algorithms may include logging in, settings checking, variable initializations, GUI loading et. After this method finishes, the “run()” method will activate.
  3. If you implemented “Ending” the “onEnd()” method will execute after the run() method, and will typically perform algorithms that your script must perform after the script ends, such as saving paint info for signatures, delivering messages to the user about what happened during the duration of running the script, etc.
  4. The rest of the methods seen will run in parallel with the rest of your script. Information for your paint will go in “onPaint(Graphics g)” and “getPaintInfo().” And the game will listen for any messages received in the chat box or pm’s etc. You can tell the script what to do in each of these cases. Such as responding to a message in the chat box. Or trading another player if you get a request.

For reference, here is a fully filled out class that I use in my Tears of Guthix script (also found in resources on my repository).

F7GiPl4.png

If your script is very simple, such as the banking one I showed earlier in a previous section, it can go straight into the “run()” method in this class. For more complicated scripts, planning, and a special framework must be designed.

5.  Framework

There has been a lot of debate as to the best framework to make for a script, and there are several to choose from. I think that there is a best one. The best one is the one that is easiest for you to use and understand. For me, that happens to be Encoded’s Task Framework Model.

You could go with a graph-based framework.

Or even the Node framework.

I won’t go into detail on the node framework or the graph-based framework. Feel free to check out those posts, which are good explanations, to discover more about them. I will provide some set up instruction for Encoded’s though.

I like Encoded’s framework because you can choose what order your script runs all of the different tasks, by prioritizing them into HIGH, MEDIUM, LOW, or NONE. The script will run those with higher priority first. Without it, if your script needs to bank, and needs to heal your hitpoints as well, your script might see that it needs to bank first if things are not ordered correctly. Then run to the bank, and when it is done with all of that, heal. With priorities, your script may set the priority of Banking to be low, and healing to be high, so it always checks your health before anything else.

Note, it is not too difficult to add a priority list to other frameworks. Like I said, pick which is best and add/remove what you like as needed.

Now lets set up your project to include the Task framework, then we will go into how to plan out a script.

Go ahead and create a new source folder in your projects and name it API. Then create a package called “scripts.framework” and add 3 classes. Name one “Priority” one “Task” and one “TaskSet:”

XsdqF3V.png

 

In “Priority,” copy and past this:

Spoiler
package scripts.framework;

public enum Priority {
	
	HIGH,
	MEDIUM,
	LOW,
	NONE
	
}

 

In “Task”, copy and past this:

Spoiler
package scripts.framework;

public interface Task {

    public abstract Priority priority();
    
    public abstract String toString();

    public abstract boolean validate();

    public abstract void execute();

}

 

In “TaskSet” copy and past this: 

Spoiler
package scripts.framework;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

@SuppressWarnings("serial")
public class TaskSet extends TreeSet<Task> {

    public TaskSet() {
        super(Comparator.comparing(Task::priority).thenComparing(Comparator.comparing(task -> task.getClass().getName())));
    }

    public TaskSet(Task... tasks) {
        super(Comparator.comparing(Task::priority).thenComparing(Comparator.comparing(task -> task.getClass().getName())));
        addAll(tasks);
    }

    public TaskSet(Comparator<? super Task> comparator) {
        this();
    }

    public TaskSet(Collection<? extends Task> c) {
        this(c.toArray(new Task[c.size()]));
    }

    public TaskSet(SortedSet<Task> s) {
        this(s.toArray(new Task[s.size()]));
    }

    public boolean addAll(Task... tasks) {
        return super.addAll(Arrays.asList(tasks));
    }

    public Task getValidTask() {
        for (Task task : this) {
            if (task.validate()) {
                return task;
            }
        }
        return null;
    }

}

 

You will need to import these into your main script class:

import scripts.framework.Task;
import scripts.framework.TaskSet;

Once done, you are all set to use the framework! Now lets walkthrough an example script to see how to implement this.

6.  Walkthrough a script

I am going to walk you through my Tears of Guthix script here. Remember though, this is the first script I ever made so a lot can be improved. Also, the script is still in beta. If you see a mistake I’ve made, most likely I’ve already found it, and fixed it! Always point it out though just in case. Also, the full script is on my github, so feel free to follow a long there, or in pictures I post!

Let's start out with how I designed the script in the first place.

5nJV7Gd.jpg

This is how I made my game plan for the script. Your entire process will go by much quicker if you enter with a plan of action. The most important parts for this section is what I put in Tasks, and validations. In tasks, I put the 4 different tasks the player can perform. Banking, going to TOG, entering TOG, and collecting tears at TOG. To get this list, I did the minigame, and went through the process of completion in my head a few times. If it were possible to do TOG more than once a week, I would have done the action repeatedly to get an idea of how I want my bot to perform.

Next was the Validation section, where I figured out when I want my bot to perform each task. I also have other pages where I list out certain common methods my script will use, and different possibilities for each task. Such as teleporting or walking to a bank.

Getting together a plan is a must. Now lets walk through the implementation.

Okay, so starting out with our main class that has our “run()” statement.

Zhb5cLX.png

Ignore the bit about paint, that’s for later. First we create a TaskSet named tasks that has each of the tasks I want to bot to perform. Note how they are the same as from my plan of action. I then loop through these tasks continuously until an end condition for the script has been met. For the user to see what task the script is performing, there is a Vars.get().status where I place a string that tells the user what is happening. More on this in a minute. Before this though, I assign a new Task, named task, that I have validated. The tasks.getValidTask() method will return a task that has validated true based on the conditions I wrote down, and it will return the one that has the highest priority as well.

Lastly, the task will execute. This execute method is where the algorithm is placed for the task to complete.

ihVAD4Q.png

Each task will be setup like this. There will a class name (“GoToTears”), and it will implement Task.

  • toString() will return a string that describes what the task is doing.

  • Priority() sets the priority of the task.

  • Validate() is where the conditions for executing this task are placed.

  • Execute() is where the algorithm is placed for the task.

When executed, the script will check if I am wearing a games necklace && am not already at TOG. It checks if I am wearing the games necklace by a method I placed in JTearsUtil and looks like this:

wdZSv99.png

*Can you find a better way to check if I am wearing a games necklace? I can! Comment below a better method for practice! Check through the API.

Then if I am, or am not wearing it, it will teleport to TOG through my inventory or my equipment screen. If it teleports successfully, it will then walk up to Juna. After this, the task is no longer valid, and it will run the EnterTOG task since it is valid. Go check out my github to follow the logic! Remember, it goes through the run method of your main class, and loops through all these tasks continuously. After a methods execute statement has been performed, the run method is called again to see if that is still the task to complete.

I used this task as a prime example of how to implement some timing, item interaction, and walking. There are several better ways to do some of these things as I have learned, but I won’t change it unless it breaks since I already wrote it. I have learned a lot since writing it. Remember to read through the API all the way through when you can! I missed several methods from it that would make life simpler.

Maybe you can rewrite the method in the comments for practice using the API? Go for it!

7.  Setting up a GUI

So, you finally have the script performing okay, and want to move on to creating a GUI. This is where I spent a whole bunch of time learning and there is a lot to it. I will try to make it simple as possible by providing several free classes that you can just copy>paste>rename right into your project! All files may be found in the resources section at the end of the tutorial.

Add a graphics package and a graphics.images package to your script and add the following classes like so:

CvMKlSG.png

Okay, lets go through these classes one at a time. Check resources to get the text in each class.

  1. GUI.java
    This class is not really going to change much. You will only need to change line 107 to whatever you want your title to be on the GUI.
    j6ckqKv.png
  2. GUIController.java
    This class will perform all the actions you need to happen in the GUI. These actions include loading a player’s equipment, saving/loading settings, performing actions when buttons are pressed etc. Scroll though mine in resources and look at it. Try and figure out what’s going on.
  3. Ignore the Paint classes for now until a later section.
  4. TutorialSettings.java
    This is a class that holds all the information from the GUI that you will need later. In your main run() class, an instance of this class will be made that holds your information.
  5.  fxml.fxml
    This is the file that you open in SceneBuilder. It holds all the information that creates the look of your GUI. The text from this file is all copied to a string in FXMLString.java.
  6. FXMLString.java
    The entire code from line one on to the end from fxml.fxml is copied here into a string (between two quote as can be seen in a later screenshot).
  7. Styles.css
    This file holds all the styles for your GUI if you choose to style it. Learn css online.

 

I recommend downloading all the files from resources and pasting the code into your own script. Make sure to rename all imports and packages as needed. Delete the example code, and put your own in.

In your onStart() method in your main class, add this bit of code. The stylesheet url has to be the raw text online somewhere. Tribot only works with class files, so the css file will not be added to the repository, so you need to get it from online. I like to use my github. (The stylesheet I use for my tears script is the same as in the tutorial, so don’t mind the address saying tears stuff)

BWbB0c5.png

To pass your settings to each Task, you will need to do something like this in each task:

s3f1vrH.png

And your main class will need to look like this when creating the TaskSet.

buIhETL.png

8.  Designing a GUI

I am going to be brief here, as the GUI is so specific to your script. There are a few things you want to make sure you do.

  1. Add your GUIController to SceneBuilder just like so in the bottom left:

    XtGnk6p.png

     
  2. When you create a button, text field, check box, etc. you need to make sure you give it an id. In the GUI controller class, create your button or whatever:

    DYCk0sJ.png

    And assign that buttons name to your button in scene builder:

    CWMOMjU.png

     
  3. In the image above, notice how there is also a ”startScript” action. This calls a method in your GUI controller class:

    majBlGp.png
     
  4. Lastly, anywhere you want to style something with a style sheet, add it to the inspector in the top right here:

    9mb3sFK.png

Here is a full example of a GUI, and is the GUI that is used in the following section.

1TJCc4i.png


Now, on to how we save settings from our GUI and use them.

9.  GUI Settings

This is the most important part for your GUI, so listen close! We are going to go over how we save, load, and export settings to our script.

 

  1. Saving and loading:
    Check out the saveSettings(), loadSettings(), getSaveFiles(), and initialize methods in the GUIController class. Each one is commented on what you need to do. Just on your SceneBuilder, attach a button to saveSettings with a text field that a user will input their settings name, and attach the loadSettings method to a load button. Also put a combo box called “avalableSettingsBox” that will have the settings you have saved in the past.
  2. Exporting settings:
    This gets a little confusing until you understand what’s going on. I will try to make it simple. All of the information you want to get from the GUI needs to be put into a settings instance that you will send to each task. The settings instance is what I have named "TutorialSettings."

    qw7c1P0.png


    I will create this instance in my main method by
    ksvdR78.png &
    1OLCIjf.png


    The method that is called in the GUIController class from the main class is:

    MPilOuc.png


    Refer to the end of section 7 on how to get the settings to each Task : )

10.  Paint

I like to keep my paint very simple. Give the needed information, and that’s it. I use Fluffee’s painting snippet to do this. Go to the API source folder we created, and add in a scripts.paint package. Add the classes below:

xJFg8be.png

FluffeesPaint.java

Spoiler
package scripts.paint;

import java.awt.*;
import java.util.Arrays;

public class FluffeesPaint {

    /**
     * Enum containing predefined locations for the paint. Each location contains a single x and y coord, with two booleans to indicate if the
     * y coordinate is at the bottom of where the text should be painted, and a second boolean to indicate if the x coordinate is at the right of where the text should be painted.
     */
    public enum PaintLocations {

        BOTTOM_LEFT_PLAY_SCREEN(5, 337, true, false),
        BOTTOM_RIGHT_PLAY_SCREEN(513, 337, true, true),
        TOP_LEFT_PLAY_SCREEN(5, 5, false, false),
        TOP_RIGHT_PLAY_SCREEN(513, 5, false, true),
        TOP_LEFT_CHATBOX(8, 345, false, false),
        TOP_RIGHT_CHATBOX(509, 345, false, true),
        BOTTOM_LEFT_CHATBOX(8, 474, true, false),
        BOTTOM_RIGHT_CHATBOX(509, 474, true, true),
        INVENTORY_AREA(551, 207, false, false);

        private int xCoordinate;
        private int yCoordinate;
        private boolean yCoordinateAtBottom;
        private boolean xCoordinateAtRight;

        PaintLocations(int xCoordinate, int yCoordinate, boolean yCoordinateAtBottom, boolean xCoordinateAtRight) {
            this.xCoordinate = xCoordinate;
            this.yCoordinate = yCoordinate;
            this.yCoordinateAtBottom = yCoordinateAtBottom;
            this.xCoordinateAtRight = xCoordinateAtRight;
        }

        public int getXCoordinate() {
            return xCoordinate;
        }

        public int getYCoordinate() {
            return yCoordinate;
        }

        public boolean isYCoordinateAtBottom() {
            return yCoordinateAtBottom;
        }

        public boolean isXCoordinateAtRight() {
            return xCoordinateAtRight;
        }
    }

    private PaintInfo paintInfo;
    private PaintLocations location;
    private Color[] fontColors, textBackgroundColors, textBackgroundBorderColors;
    private String[] paintInformationArray;
    private String fontName;
    private int borderThickness, numberOfItems, horizontalPadding, verticalPadding;
    private int[] xCoords, yCoords;
    private boolean singleBackground;
    private PaintableText[] paintableTexts;
    private PaintableText paintableText;
    private GraphicsEnvironment graphicsEnvironment;
    private int spaceBetweenFields;
    private static final long START_TIME = System.currentTimeMillis();

    /**
     * Constructor to create the paint, arguments passed define how the paint will appear.
     *
     * @param paintInfo                  The paintInfo object you created, usually this will be the script class that extends PaintInfo. This object allows us to update the paint info for things like script runtime, exp/hr, etc.
     * @param location                   The location on the screen in which the paint is to be placed, from the enum defined above.
     * @param fontColors                 Array of Color which represents the font colors to use. If the array is longer than the number of Strings in the info array it will be shortened. If it is shorter the
     *                                   last element of the array will be copied until the array is the same length as the number of Strings in the info array.
     * @param fontName                   Font name to use to print the text, as a String. This name is checked, and will be replaced if it is unavailable.
     * @param textBackgroundColors       Array of Color which represents the background colors to use. Backgrounds will be drawn behind the text in the paint. If you do not want a background,
     *                                   make the Color completely transparent. If the array is longer than the number of Strings in the info array it will be shortened. If it is shorter the
     *                                   last element of the array will be copied until the array is the same length as the number of Strings in the info array.
     * @param textBackgroundBorderColors Array of Color which represents the border colors to use. Borders will be drawn around where the background of the text is on the paint. If you do
     *                                   not want a background, make the Color completely transparent. If the array is longer than the number of Strings in the info array it will be shortened.
     *                                   If it is shorter the last element of the array will be copied until the array is the same length as the number of Strings in the info array.
     * @param borderThickness            Thickness of the border to draw. If you do not want a border, make the border thickness 0.
     * @param singleBackground           A boolean, true if you want one background behind all text, false if you want backgrounds drawn individually.
     * @param spaceBetweenFields         The space in pixels to place between the painted Strings. If using multiple backgrounds the space accounts for the backgrounds, and will be the space
     *                                   between where the backgrounds end.
     * @param horizontalPadding          Padding to add horizontally to the printed Strings, measured in pixels. Padding is whitespace, and will create space between the text and edge of background
     * @param verticalPadding            Padding to add vertically to the printed Strings, measured in pixels. Padding is whitespace, and will create space between the text and edge of background
     */
    public FluffeesPaint(PaintInfo paintInfo, PaintLocations location, Color[] fontColors, String fontName, Color[] textBackgroundColors, Color[] textBackgroundBorderColors, int borderThickness, boolean singleBackground, int spaceBetweenFields, int horizontalPadding, int verticalPadding) {
        this.paintInfo = paintInfo;
        this.paintInformationArray = new String[]{""};
        this.location = location;
        this.graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        this.numberOfItems = 0;
        this.fontColors = copyOfNoNulls(fontColors, numberOfItems == 0 ? fontColors.length : numberOfItems);
        this.fontName = Arrays.stream(graphicsEnvironment.getAvailableFontFamilyNames()).anyMatch(fontName::equals) ? fontName : graphicsEnvironment.getAvailableFontFamilyNames()[0]; //StackExchange one liner to match a String.
        this.textBackgroundColors = copyOfNoNulls(textBackgroundColors, numberOfItems == 0 ? textBackgroundColors.length : numberOfItems);
        this.textBackgroundBorderColors = copyOfNoNulls(textBackgroundBorderColors, numberOfItems == 0 ? textBackgroundBorderColors.length : numberOfItems);
        this.borderThickness = borderThickness;
        this.singleBackground = singleBackground;
        this.xCoords = new int[numberOfItems];
        this.yCoords = new int[numberOfItems];
        this.spaceBetweenFields = spaceBetweenFields;
        this.horizontalPadding = horizontalPadding;
        this.verticalPadding = verticalPadding;
    }

    /**
     * Method used to create a single PaintableText object, used for painting text with a single background.
     *
     * @param graphics - Graphics object.
     * @return PaintableText object which contains the text to be painted, the background, border, etc.
     */
    private PaintableText createPaintableText(Graphics graphics) {
        graphics.setFont(Font.getFont(fontName));
        FontMetrics fontMetrics = graphics.getFontMetrics();
        int textHeight = fontMetrics.getHeight();
        int xMultiplier = location.isXCoordinateAtRight() ? -1 : 0;
        int startingX = location.isXCoordinateAtRight() ? location.getXCoordinate() - horizontalPadding : location.getXCoordinate() + horizontalPadding;
        int startingY = location.isYCoordinateAtBottom() ? location.getYCoordinate() - verticalPadding - ((textHeight + spaceBetweenFields) * numberOfItems - 1) : location.getYCoordinate() + verticalPadding;
        for (int i = 0; i < numberOfItems; i++) {
            xCoords[i] = startingX + (xMultiplier * (int) fontMetrics.getStringBounds(paintInformationArray[i], graphics).getWidth());
            yCoords[i] = startingY + ((int) fontMetrics.getStringBounds(paintInformationArray[i], graphics).getHeight() + spaceBetweenFields) * (i + 1);
        }
        return new PaintableText(fontColors[0], textBackgroundColors[0], textBackgroundBorderColors[0], paintInformationArray, borderThickness, horizontalPadding, verticalPadding, xCoords, yCoords);
    }

    /**
     * Method used to create an array of PaintableText objects, used for painting text with separate backgrounds.
     *
     * @param graphics - Graphics object.
     * @return PaintableText object array each object contains the text to be painted, the background, border, etc.
     */
    private PaintableText[] createPaintableTexts(Graphics graphics) {
        PaintableText[] paintableTexts = new PaintableText[numberOfItems];
        graphics.setFont(Font.getFont(fontName));
        FontMetrics fontMetrics = graphics.getFontMetrics();
        int textHeight = fontMetrics.getHeight();
        int xMultiplier = location.isXCoordinateAtRight() ? -1 : 0;
        int startingX = location.isXCoordinateAtRight() ? location.getXCoordinate() - horizontalPadding : location.getXCoordinate() + horizontalPadding;
        int startingY = location.isYCoordinateAtBottom() ? location.getYCoordinate() - ((((verticalPadding * 2) + (borderThickness * 2) + textHeight + spaceBetweenFields) * (numberOfItems)) + verticalPadding + borderThickness) : location.getYCoordinate() + verticalPadding;
        for (int i = 0; i < numberOfItems; i++) {
            xCoords[i] = startingX + (xMultiplier * (int) fontMetrics.getStringBounds(paintInformationArray[i], graphics).getWidth());
            yCoords[i] = startingY + (textHeight * i) + ((spaceBetweenFields + (verticalPadding * 2) + (borderThickness * 2)) * i);
            paintableTexts[i] = new PaintableText(fontColors[i], textBackgroundColors[i], textBackgroundBorderColors[i], paintInformationArray[i], borderThickness, horizontalPadding, verticalPadding, xCoords[i], yCoords[i]);
        }
        return paintableTexts;
    }

    /**
     * Paints the information on the screen by creating the PaintableText objects and painting them individually.
     *
     * @param graphics
     */
    public void paint(Graphics graphics) {
        if (paintInfo.getPaintInfo() == null || paintInfo.getPaintInfo().length < 1) {
            return;
        }
        if (Arrays.equals(paintInformationArray, paintInfo.getPaintInfo())) { //Used to avoid recalling the creation methods if nothing has changed.
            if (!singleBackground) {
                for (PaintableText text : paintableTexts) {
                    text.paintComponent(graphics);
                }
            } else {
                paintableText.paintComponent(graphics);
            }
        } else {
            if (numberOfItems == 0) { //Only occurs when there's nothing to paint, or it hasn't loaded due to the paint loading before the script.
                reinitializeVariables();
            } else { //If the numberOfItems != 0 then the only thing that's changed is the text to paint, so we'll just update that.
                this.paintInformationArray = paintInfo.getPaintInfo();
                reinitializeVariables();
            }
            if (!singleBackground) {
                this.paintableTexts = createPaintableTexts(graphics);
                for (PaintableText text : paintableTexts) {
                    text.paintComponent(graphics);
                }
            } else {
                this.paintableText = createPaintableText(graphics);
                paintableText.paintComponent(graphics);
            }
        }
    }

    /**
     * Reinitializes all variables if something has changed, used when the info to paint has changed from what it was previously.
     * Used to save on unnecessary method calls if the paint text hasn't changed, as the Paint thread runs frequently.
     */
    private void reinitializeVariables() {
        this.paintInformationArray = paintInfo.getPaintInfo();
        this.numberOfItems = paintInformationArray.length;
        this.fontColors = copyOfNoNulls(fontColors, numberOfItems);
        this.fontName = Arrays.stream(graphicsEnvironment.getAvailableFontFamilyNames()).anyMatch(fontName::equals) ? fontName : graphicsEnvironment.getAvailableFontFamilyNames()[0]; //StackExchange one liner to match a String.
        this.textBackgroundColors = copyOfNoNulls(textBackgroundColors, numberOfItems);
        this.textBackgroundBorderColors = copyOfNoNulls(textBackgroundBorderColors, numberOfItems);
        this.xCoords = new int[numberOfItems];
        this.yCoords = new int[numberOfItems];
    }

    /**
     * Returns the time that the current script has ran for. Based off of the start time created when the script starts.
     * Could use the method in the script, but wanted to avoid passing a script object.
     * @return The current runtime of the script as a String.
     */
    public String getRuntimeString() {
        long millis = System.currentTimeMillis() - START_TIME;
        long second = (millis / 1000) % 60;
        long minute = (millis / (1000 * 60)) % 60;
        long hour = (millis / (1000 * 60 * 60)) % 24;
        return String.format("%02d:%02d:%02d", hour, minute, second);
    }

    /**
     * Returns the baseColor with the applied transparency to make the alpha conversion easier.
     *
     * @param baseColor    Color to make transparent
     * @param transparency How transparent to make the color, 100 is completely transparent, 0 is completely opaque
     * @return BaseColor with the applied transparency
     */
    public static Color makeTransparentColor(Color baseColor, int transparency) {
        return new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), (int) (((double) ((transparency - 100) * -1) / 100) * 255));
    }

    /**
     * Copies the passed array into the specified length. Will copy the last element multiple times to fill the remaining space, or cut the array to shorten.
     *
     * @param original    Starting array
     * @param arrayLength Length to make the resulting array
     * @param <T>         Generic type.
     * @return Array of passed type at the required length.
     */
    private <T> T[] copyOfNoNulls(T[] original, int arrayLength) {
        T[] newArray = Arrays.copyOf(original, arrayLength);
        if (original.length < arrayLength) {
            for (int i = original.length; i < newArray.length; i++) {
                newArray[i] = newArray[i] == null ? original[original.length - 1] : newArray[i];
            }
        }
        return newArray;
    }

}

 

PaintableText.java

Spoiler
package scripts.paint;

import javax.swing.*;
import java.awt.*;

@SuppressWarnings("serial")
public class PaintableText extends JComponent {

    private Color fontColor, backgroundColor, borderColor;
    private String[] infoToPaint = null;
    private String textToPaint;
    private int borderThickness, leftmostX, rightmostX, lowestY, highestY, horizontalPadding, verticalPadding, xCoord, yCoord;
    private int[] xCoords, yCoords;

    /**
     * PaintableText Constructor for use when wanting only one background for all text.
     * @param fontColor Font color to use for the font in the paint.
     * @param backgroundColor Background color to use in the paint.
     * @param borderColor Border color to use in the paint.
     * @param infoToPaint String array containing the info to paint on screen.
     * @param borderThickness How thick to draw the border around the background
     * @param horizontalPadding How much space to have between the left/right edge of the background and the text
     * @param verticalPadding How much space to have between the top/bottom edge of the background and the text
     * @param xCoords X Coordinates to use to paint the strings, one per string
     * @param yCoords Y Coordinates to use to paint the strings, one per string.
     */
    public PaintableText(Color fontColor, Color backgroundColor, Color borderColor, String[] infoToPaint, int borderThickness, int horizontalPadding, int verticalPadding, int[] xCoords, int[] yCoords) {
        this.fontColor = fontColor;
        this.backgroundColor = backgroundColor;
        this.borderColor = borderColor;
        this.infoToPaint = infoToPaint;
        this.borderThickness = borderThickness;
        this.horizontalPadding = horizontalPadding;
        this.verticalPadding = verticalPadding;
        this.xCoords = xCoords;
        this.yCoords = yCoords;
        this.leftmostX = getMinValue(xCoords);
        this.rightmostX = getMaxValue(xCoords);
        this.highestY = getMinValue(yCoords);
        this.lowestY = getMaxValue(yCoords);
    }

    /**
     * PaintableText Constructor for use when wanting only one piece of text per background.
     * @param fontColor Font color to use for the font in the paint.
     * @param backgroundColor Background color to use in the paint.
     * @param borderColor Border color to use in the paint.
     * @param textToPaint Text to paint on screen.
     * @param borderThickness How thick to draw the border around the background
     * @param horizontalPadding How much space to have between the left/right edge of the background and the text
     * @param verticalPadding How much space to have between the top/bottom edge of the background and the text
     * @param xCoord X Coordinate to use to paint the string.
     * @param yCoord Y Coordinate to use to paint the string.
     */
    public PaintableText(Color fontColor, Color backgroundColor, Color borderColor, String textToPaint, int borderThickness, int horizontalPadding, int verticalPadding, int xCoord, int yCoord) {
        this.fontColor = fontColor;
        this.backgroundColor = backgroundColor;
        this.borderColor = borderColor;
        this.textToPaint = textToPaint;
        this.borderThickness = borderThickness;
        this.horizontalPadding = horizontalPadding;
        this.verticalPadding = verticalPadding;
        this.xCoord = xCoord;
        this.yCoord = yCoord;
    }

    /**
     * Method used to paint the component on the screen.
     * @param graphics Graphics object passed.
     */
    @Override
    public void paintComponent(Graphics graphics) {
        if (infoToPaint != null) { //Flag to switch between printing multiple backgrounds, or just one. In this case, just one background.
            highestY = highestY - (graphics.getFontMetrics().getHeight()); //Moves the highestY point to the top of where the text will be drawn. Text must be drawn at the bottom left corner, whereas rectangles are drawn at top left.
            rightmostX = leftmostX + (int) graphics.getFontMetrics().stringWidth(getWidestString(infoToPaint, graphics)); //Determines the farthest right point by adding the width of the widest string to the leftmost point.
            graphics.setColor(backgroundColor);
            graphics.fillRect(leftmostX - horizontalPadding, highestY - verticalPadding, (rightmostX + horizontalPadding) - (leftmostX - horizontalPadding), (lowestY + verticalPadding) - (highestY - verticalPadding));
            Graphics2D graphics2D = (Graphics2D) graphics;
            if (borderThickness > 0) { //Only draw border if the border width is greater than 0, otherwise you don't want a border.
                graphics2D.setColor(borderColor);
                graphics2D.setStroke(new BasicStroke(borderThickness)); //Sets graphics2D to draw a border of the specified width.
                graphics2D.drawRect(leftmostX - horizontalPadding, highestY - verticalPadding, (rightmostX + horizontalPadding) - (leftmostX - horizontalPadding) + borderThickness, (lowestY + verticalPadding) - (highestY - verticalPadding) + borderThickness);
            }
            graphics.setColor(fontColor);
            for (int i = 0; i < infoToPaint.length; i++) {
                graphics.drawString(infoToPaint[i], xCoords[i], yCoords[i]); //Draws the Strings at their appropriate coordinates.
            }
        } else {
            Graphics2D graphics2D = (Graphics2D) graphics;
            Rectangle textRectangle = graphics.getFontMetrics(graphics.getFont()).getStringBounds(textToPaint, graphics).getBounds(); //Creates a rectangle object that is the size of the String to paint.
            int textHeight = (int) textRectangle.getHeight(); //Creates textHeight variable so I can modify the rectangle.
            textRectangle.setLocation(xCoord - horizontalPadding + borderThickness, yCoord - verticalPadding + borderThickness); //Moves the rectangle to the appropriate place for the background.
            textRectangle.setSize((int) textRectangle.getWidth() + horizontalPadding + horizontalPadding, (int) textRectangle.getHeight() + verticalPadding + verticalPadding); //Increases the size of the rectangle to account for padding
            graphics2D.setColor(backgroundColor);
            graphics2D.fill(textRectangle);
            graphics2D.setColor(fontColor);
            graphics2D.drawString(textToPaint, xCoord, yCoord + (int) (textHeight * 0.80)); //Multiplies the textHeight by 0.80 to try and center it vertically a bit better. If you think it's off, feel free to toy around with that value.
            if (borderThickness > 0) {
                graphics2D.setStroke(new BasicStroke(borderThickness));
                graphics2D.setColor(borderColor);
                graphics2D.drawRect(xCoord - horizontalPadding, yCoord - verticalPadding, (int) textRectangle.getWidth() + borderThickness, (int) textRectangle.getHeight() + borderThickness);
            }
        }
    }

    /**
     * Gets the highest number in an integer array.
     * @param numbers Array to check through
     * @return Highest number in the array.
     */
    public int getMaxValue(int[] numbers) {
        if (numbers.length < 1) {
            return Integer.MIN_VALUE;
        }
        int maxValue = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            if (numbers[i] > maxValue) {
                maxValue = numbers[i];
            }
        }
        return maxValue;
    }

    /**
     * Gets the lowest number in an integer array.
     * @param numbers Array to check through
     * @return Lowest number in the array.
     */
    public int getMinValue(int[] numbers) {
        int minValue = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
            if (numbers[i] < minValue) {
                minValue = numbers[i];
            }
        }
        return minValue;
    }

    /**
     * Returns the String which will be the widest when drawn, out of an array of Strings
     * @param stringArray Array to check through
     * @param graphics Graphics object that will be used to paint the Strings
     * @return The String that will take up the most space.
     */
    private String getWidestString(String[] stringArray, Graphics graphics) {
        if (stringArray.length < 1) {
            return null;
        } else if (stringArray.length == 1) {
            return stringArray[0];
        }
        FontMetrics fontMetrics = graphics.getFontMetrics();
        int index = 0;
        int elementWidth = fontMetrics.stringWidth(stringArray[0]);
        for (int i = 1; i < stringArray.length; i++) {
            if (fontMetrics.stringWidth(stringArray[i]) > elementWidth) {
                index = i;
                elementWidth = fontMetrics.stringWidth(stringArray[i]);
            }
        }
        return stringArray[index];
    }
}

 

PaintInfo.java

Spoiler
package scripts.paint;

/**
 * Created by Fluffee on 09/01/18.
 */
public interface PaintInfo {

   public String[] getPaintInfo();

}

 

Add something like this to your main method:

kVz90TH.png

It describes where your paint will be on the screen and the colors etc. Check out the constructor in the api to figure out the possible settings. We also need these two methods in our main class:

iUctp0W.png

This will add the paint to the screen, and display the information in getPaintInfo respectively. Lastly, the PaintInfoThread class in your graphics package will look similar to this:

yEj3YAy.png

This contains a thread that will continuously run, updating your paint continuously. Any information that is updated continuously, such as xp, should be put here. In this example, all I have it doing is obtaining the runtime of the script. Add additional tracking between “Vars.get.runtime…” and “try {“.

For additional information, check out the resources section!

11.  Anti ban

This is a very difficult topic to cover, so I will do my best to give it justice. Before we do though, check out Trilez’s guide to implementing ABC2. (check out resources)

This feature of your script is argueably the most important, yet hardest to implement. It results in very slight, hardly noticeable changes to your scripts performance, yet it takes hours, and hundreds of lines of code. Through all of that darkness though, you find a path that leaps over the dead RS accounts stuck on world 401.

Read through ABCUtil on the API before continuing. Complex right? The whole idea here is human emulation. A very hard topic to cover. Here is an example: you want the bot to seem less bot like so you pick a random time to turn the camera, a random time to eat your food, or click the next target. You get banned. Why? Because humans are not random, we follow a strict pattern unique to each one of us. Sometimes the pattern changes and evolves. We are definitely not random though. The ABCUtil (Anti Ban Compliance Utility) Does the best job it can an looking more human. It will generate reaction time for changes in the game based on certain number distributions that we set, and our past reaction times, and much more. It really is up to you on how you implement this, but you can check out my github to see how I did it on my Tears of Guthix script. It boils down to figuring out if you SHOULD do something, then DOING that something. i.e. shoudCheckXP = true? Okay, checkXP. Another example: A fishing spot has just moved locations. What to do: generateReactionTime -> wait for that reaction time.

For more examples, check out the resource section!

12.  Your own API

 

This is something that your should be doing consistently, and periodically throughout your scripting career. Just like Tribot has an API, you should have one too. You are encouraged to share it as well in the Snippets or Tools section of the forum. What goes in your API are things that You need to perform periodically in your scripts, that a simple method could do. Don’t put things specific to your script here though.

If you do not like a method in the API such as how it detects if you are in a bank. Yes, I do not like the default method, it doesn’t detect chests very well in my experience and does not detect far enough away as I’d like. (Standing next to chest in lumby basement, and it says I am not in bank, rude.). So, I created my own, rather I found one in the snippets section, and added it to my API. Now, any script that needs to detect if I am in a bank, I just use my own snippet instead of the default. I do this for several tasks that I perform frequently, and it makes the process of creating a script much more efficient!

This is why I had you add some classes to an API source in eclipse. It makes it much simpler to create new scripts.

13.  Debugging

Okay, I am ready to run my script after hours of coding and much coffee. It doesn’t do anything. What happened??? I got no errors and it just doesn’t do what it is supposed to! Or…. Why is it running to the bank after it already banked! Or… Null pointer exceptions etc. etc. etc. Everyone has their own way of finding where the errors are in their script. I like to do it like so:

So, how do we fix our script when something goes wrong? Check out an example from the Task in my TOG script that will collect the tears for me. Look for the places I have General.println(); for where I check the location of the script in the bot debugger:

mRHJmRb.png

In every section of the Task, I have a message that will print out to the client debugger about where I am at in the code. If it is a place where it shouldn’t be, I will follow the code and see what conditions have to be met to get there. Likely something is wrong. If I get some type of pointer exception, the bot debug will tell you where the issue was.

There are ways that you can step through the code bit by bit in eclipse, but I don’t like that method so I do this. Plus it entertains me to write some unique comments. Like “General.println(“In this class, we should not be you Jedi”);” hehe 😊

Your script is your script. You should be able to work through your own code and find out why something is not working right. Rarely will you find that Java, or an API method is actually the problem. It is most likely your syntax (how you wrote your code).

  1. Identify your problem.

  2. Identify where in your code the problem could be, i.e. which task or method.

  3. Read through the code and try to identify the issue.

  4. Use things like General.println() like I showed above to see where the code stops following the logical path it should.

  5. Check variables inside the General.println() as well.

14.  Useful tools/snippets

  1. Encoded's Map

  2. Dax Webwalker

  3. Functional Condition

  4. aCamera

  5. ingame world hopping

  6. lantools

  7. Einstein area builder

  8. RSVarbit explorer

  9. Settings explorer

  10. Laniax entity selector

  11. Dax inventory listener

  12. Shop api

  13. Automatic banking api

  14. Interface explorer - This one is in tribots client!

  15. More Snippets and Tools!

Note: Some of these tools are outdated and you need to fix them up before they work!

15.  Repository

Now you want Tribot glory. You have created one helluva script and want to be one helluva celebrity. Time to upload it so the world can see. This is very simple actually.

  1. Make a forum thread describing your script
  2. Go to the .tribot folder on your computer and place all of the source folders you see there that are used in your script into a zip file.
  3. Upload that zip files to the scripters section of the repository
  4. Done!

Problems may occur when doing this. Remember, anything in your script that grabs a file from your computer, that is not a class file, will not be added to the repository. They need to be put online, and the raw text needs to be linked in the script.

NAlEHXw.png

Make sure you copy pasted your text from fxml.fxml to FXMLString, right between the quotes:

4hgeseu.png

Make sure that each place you have @FXML in your GUIController class also has @DoNotRename:

eVyrrMD.png

16.  Navigating the site

The website will be your best resource for information regarding scripting. There are a few places you should check when you have an issue.

  1. Check the Scripting Help forum for issues regarding issues in your script. Likely case, is your question has been asked. Do a search.

  2. Snippets – great place to make your life easier. Many people post things from their API here.

  3. Tools – as stated in the tools section, it does wonders.

  4. PM scripters with help, most are willing to help! You can PM me too even though I don't have the scripter title :)

  5. Go through this approved scripter application thread to get many script examples.

17.  Good practices

  • Test your codes methods, tasks, and all before you put it all together. It is much easier to trouble shoot one things rather than a jumbled mess.
  • Do not code linearly. Code  your script to detect exactly where it is and what it should be doing at that time. Don’t have your script do the exact same thing in a linear sequence. Else you will just get stuck somewhere with a little bit of lag or something.
  • Read other scripters source code. I cannot stress how useful this is enough. I will link several source code examples in references. My code is by far not the best, but it will still help. Others will help more.
  • Read, and re-read the tribot API.
  • Always null check your values. If you check to see if an item exists, then you use the same method again to get that item, you will likely encounter problems at some point. Calling a method twice does not always give the same result. Instead, place the item into a variable, check if it is null, and if not, perform actions on it.
  • Check the lengths of your arrays before indexing them. Your script will stop if you try to get the 5th element of an array but only 4 exist.
  • Always exit loops naturally in your code. Make sure that even if something goes wrong, eventually, the lop will end. Try placing a timer inside of it just in case something goes wrong.
  • While loops execute extremely fast. Add a sleep into each loop so that it slows down and uses less CPU.
  • Any time a returned value from a method is used more than once, store it into a variable.

18.  Resources

Check out my github here for all the files I used in the tutorial! Some may have been updated since I wrote the tutorial.

Here is a full script template you can use. It uses the methods I described in this tutorial. Just refactor the name of the files and you are good.

Also check out some of these guides below. Without them, I would not have been able to learn nearly as much as I have!

Einsteins scripting tutorials 1 and 2

Natons JavaFX tutorial

Trilez Scripting tutorial and ABC tutorial

Here are a few githubs of people I used to help me learn.

Naton, Einstein

@Naton and @Einstein Let me know if I should remove.

 

All Done! Thank you to everyone for reading through it. Especially thanks to everyone who created the tools, and guides that I have used in making this tutorial!

 

 

 

 

 

 

Edited by Jerminater
Anti-bully measures
  • Like 4
  • Thanks 1

Share this post


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

Naming conventions and brace placements/lack of in some places are cancer. More so just a walk through of how you when about doing your script than an actual scripting tutorial.

Thanks for the kind and constructive criticism! Great member of the community. :) if you would like to point exactly where I made some mistakes let me know! I will do my best to fix them. I am fairly new, and put a lot of time into this. Time will be put further into it to improve as time goes on. 

Also, this is a guide to get people set up who do not know anything about scripting with tribot. I have linked and mentioned several ways to do things as a large collection of information for people. 

Edited by Jerminater

Share this post


Link to post
Share on other sites
2 hours ago, Jerminater said:

elH77j2.png

Either use no braces for 1 line ifs or dont. Imo if your going to pyramid ifs the outer ones should use braces, not sure what the standards are for that tho.

Stuff like haveGames or wearingGames should be named like isWearingGames or hasGames. Plenty more probably, but cba reading through it all.

 

 

 

 

Share this post


Link to post
Share on other sites
Posted (edited)

@Deluxes

It was my understanding that in order to link the else statement to the correct if statement, I had to put a curly bracket. Upon looking just now, I find this from oracle documentation: "The Java programming language, like C and C++ and many programming languages before them, arbitrarily decrees that an else clause belongs to the innermost if to which it might possibly belong." Since this is the case, I do not need the curly and was mistaken. I'll update the image.

For your second comment, The naming conventions for methods are that they start with a lowercase letter, and must be a verb. Both of these names follow the correct convention. 

Edit: Wearing is an adjective not a verb, so I guess that one could be changed.

Edited by Jerminater

Share this post


Link to post
Share on other sites
29 minutes ago, Jerminater said:

@Deluxes

It was my understanding that in order to link the else statement to the correct if statement, I had to put a curly bracket. Upon looking just now, I find this from oracle documentation: "The Java programming language, like C and C++ and many programming languages before them, arbitrarily decrees that an else clause belongs to the innermost if to which it might possibly belong." Since this is the case, I do not need the curly and was mistaken. I'll update the image.

For your second comment, The naming conventions for methods are that they start with a lowercase letter, and must be a verb. Both of these names follow the correct convention. I am sorry you dislike the sound of them.

 

Edit: Wearing is an adjective not a verb, so I guess that one could be changed.

Methods that return booleans and do nothing else follow is/has/can/should prefixes. Example ArrayList#isEmpty vs ArrayList#remove. isEmpty just returns if its empty or not, while remove does an action inside of the method.

https://wiki.eclipse.org/Recommenders/CodingConventions

HtJ0nQ9.png

Share this post


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

Methods that return booleans and do nothing else follow is/has/can/should prefixes. Example ArrayList#isEmpty vs ArrayList#remove. isEmpty just returns if its empty or not, while remove does an action inside of the method.

Well some things you learn as you go I guess. Can only know what you've read, or what someone has told you. Thanks for pointing it out, I will know for the future.

Next time you want to comment on someone else's post though, don't go calling them cancer, or what they do cancer. It is very rude. Just make a comment suggesting improvement. You will be seen as a better person, and get better responses.

  • Like 2

Share this post


Link to post
Share on other sites
11 hours ago, DeriveSoHard said:

Nice guide, very thorough and in-depth for beginners. You recognize that Antiban is arguably one of the most difficult concepts for beginners to grasp and I would encourage you to make another guide on Antiban, with more detail. 

Thanks! I plan on doing an extension to Trilez's tutorial sometime in the future. Working on a big move right now though so do not have much development time.

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
        • Thanks
        • Like
      • 44 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
        • Like
      • 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
        • Thanks
        • Like
      • 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
        • Like
      • 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
        • Thanks
        • Like
      • 38 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×