Jump to content

All-in-one programming guide for programmers


feggit

Recommended Posts

I've been writing scripts for my own for a short time. I have a fair amount of knowledge in (Java) programming because I major in Computer Science. In the beginning, I didn't know how to write scripts for the OSBot and it took me a long time to understand it. I'll put useful links to other topics and I'll add my own knowledge to this topic. I hope veteran scripters can tell me if I am saying anything incorrect, so I can learn from it.

This guide is not to teach you how to program, but it is targeted to people who already know how to program but just don't know how to start. If you want to learn how to program in Java, there are other tutorials for it like this one and that one. [1, 2]

I'll be updating this thread when I discover something new or when mistakes have been made as I am a beginner myself.

!!! IMPORTANT !!!

Everything you need to know about the OSBot API can be found in the Javadocs of the OSBot API.

Choosing IDE, importing libraries and compiling

Spoiler

Popular IDE's are IntelliJ and Eclipse. When starting programming in Java, I used Eclipse, but then others recommended IntellJ so I now used IntelliJ.

The libraries you have to import is the OSBot client file. You need to compile and build the .class file, which you need to put in your OSBot folder [3].

Skeleton code

Spoiler

The minimum code you need to given here [4]. Your bot script should be a subclass of Script, which is a subclass of MethodProvider.

Method Provider class

Spoiler

 

The MethodProvider class provides you all the method you need. By calling certain methods, you'll get an instance of a class returned of which you can call the methods to do certain actions. A few examples that I have used are given below.


/* Example */
getWalking().walk(new Position(0, 0, 0)); //Walks to (0, 0, 0)

if (getSkills().getDynamic(Skill.HITPOINTS) < getSkills().getStatic(Skill.HITPOINTS)) { //Checks if HP is full.
	//Eat
}

getBank().depositAll() //Deposit all items in bank.

List<String> message = getChatbox().getMessages(Chatbox.MessageType.PLAYER) //Returns all chat messages by players in the chatbox including names.
  
int inventorySpace = getInventory().getEmptySlotCount(); //Get amount of empty spaces in your inventory;
  
myPlayer().getPosition(); //Get position of your player
myPosition() //Same
  
//Speaks for itself
myPlayer().isAnimating(); 
myPlayer().isMoving();
myPlayer().isUnderAttack();

 

  

Logs

Spoiler

You may want to log messages like System.out.println() by using the log() method to see the messages in the logger. 


/* Example */
log("Hello World");

image.png.a86c8645c47d2221d7205cf2f7f4eeb1.png

 

Positions and Areas

Spoiler

 

Position and Area are classes to define positions and areas in the game. A Position is defined by the (x, y, z)-coordinates of the game. An Area is a set of Positions, which means you can define a area of a certain house by giving the (x,y) coordinates of two opposite corners, though there are other ways to define an area.

NOTE: Areas of banks are already predefined here.


/* Example */
Position grandExchangePosition = new Position(3165, 3487, 0); //Somewhere in Grand Exchange
Area grandExchangeArea = new Area(3162, 3492, 3167, 3487); // The middle of Grand Exchange
Area grandExchangeArea2 = Banks.GRAND_EXCHANGE;

 

 

 

Walking

Spoiler

 

There are mainly three ways to walk. WalkWalkPath and WebWalk.  Walk is for short distances (10 tiles or so) and WebWalking is for long distances. WalkPath is to walk a path, by giving it a set of Position objects.  If you do not provide a list of position, WalkPath will generate a path. However, WalkPath does not handle obstacles, WebWalking does. Yet, WebWalking consumes more resources [5, 6, 9]. 

On 9/14/2017 at 3:03 PM, Apaec said:
  • walkPath does not handle obstacles
  • walkPath does not generate a path so presumable less cpu/ram, although neither use a huge amount
  • walkPath is more reliable as it is not required to generate a path

Rule of thumb: Use walkPath where possible, use walk for very short distances (i'd say no more than 10 tiles to be safe), use webWalk if the place that you're walking from is unknown.

 

 

 

Entities

Spoiler

The Entity class is the superclass of the Player, NPC, RS2Object classes. These three classes are the things you can interact with in the game. Another player can be represented by a Player object, Hans can be represented by an NPC object and a door can be represented by an NPC object. You can get all players, all npcs and all objects by methods of the MethodProvider class. You can then interact with those entites. By interacting, you can let the player do the option that can be chosen when you right-click something in the game.

 


/* Example */
List<Player> players = getPlayers().getAll(); //Get the list of all players.
players.get(0).interact("Attack");  //Attack the first player in the list.

getNpcs().closest("Hans").interact("Age"); //From all the NPCs, get the closest NPC named "Hans" and use the "Age" option.

getObjects().closest("Rock").interact("Mine"); //Mine the closest rock.

 

Dialogues

Spoiler

Dialogues is for speaking to an NPC, useful for questing when you need to choose your answers/actions.


/* Example */
NPC horacio = getNpcs().closest("Duke Horacio"); //NPC from Rune Mysteries
horacio.interact("Talk-to");
getDialogues().completeDialogueU("Have you any quests for me?", "Sure, no problem.") //Completing the dialogue

 

ExperienceTracker

Spoiler

When making a script to do a certain skill, you may want to keep track of how many xp the player has gained and how much time has elapsed since the start of the script. You can do this by using the ExperienceTracker.


/* Example */
@Override
public void onStart() {
	ExperienceTracker experienceTracker = getExperienceTracker();
	experienceTracker.start(Skill.RANGED); //Start of tracking Ranged.
}
        
@Override
public void onPaint(Graphics2D g) {
    g.setColor(Color.white);
    g.drawString("Xp: " + experienceTracker.getGainedXP(Skill.RANGED), 0); //XP gained since start.
    Date date = new Date(experienceTracker.getElapsed(Skill.RANGED) - 3600*1000); //Time elapsed since start.
    DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    String dateFormatted = formatter.format(date);
    g.drawString("Time: " + dateFormatted, 0);
}

 

(Conditional) Sleep and Random Number Generator

Spoiler

 

Your script sometimes needs to have sleeps, for instance waiting until the ore has been replenished, or waiting a moment to mine the rock after the ore has been replenished. You can sleep two ways by using sleep() and ConditionSleep. sleep() is to sleep x miliseconds. ConditionalSleep is an object used for sleeping until a condition has been satisfied.


/* Example */

sleep(1000) //Sleeps exactly 1000 ms i.e. 1 second.

new ConditionalSleep(10000, 2000) { //Timeout for this sleep is 10.000 ms i.e. 10 seconds, and the condition check is every 2000 ms i.e. 2 seconds [9].
    @Override
    public boolean condition() throws InterruptedException {
        return getSkills().getStatic(Skill.SLAYER) == 99; //Sleeps until Slayer is 99
    }
}.sleep();

 

Instead of using uniformly distributed numbers (meaning all numbers have equal chance to be returned by the Random number generator), one could use the function nextGaussian() for the random sleeping times, which gives a normal distributions on the numbers the method returns. You can use this website to see how your normal distribution looks like with a defined mean and standard deviation [7]. The mean should be the number that has the highest chance of being returned by the random number generator. The standard deviation is to define the deviation of the numbers returned by the random number generator. A lower the standard deviation means the random generator numbers are closer to the mean.


/* Example */
Random random = new Random();
int stdev = 1;
int mean = 2
sleep(random.nextGaussian() * stdev + mean);

 

GUI and Locks

Spoiler

Lots of scripts has a GUI (pronounced as Gee-You-Eye or Gooey xD) window shown when starting a script, where you can set the settings. The GUI is done by Java AWT. When this GUI is shown, the script should be locked at the beginning, waiting for you to click the start button. How to make these can be found here [8].

MouseListeners and KeyListeners

Spoiler

If you want to detect moves from for example your mouse or keyboard (pressing F1 to show your GUI for settings), you can use BotMouseListeners and BotKeyListeners. KeyEvent and MouseEvent (subclass of InputEvent) both have a method consume() [9]. By invoking this method, the key won't be send to the game. For example F2 is the shortkey for opening the Stats tab. By consuming the event, the Stats tab won't open.

Be sure to add your listeners, or it won't work. 

 


BotKeyListener botKeyListener = new BotKeyListener() {
    @Override
    public void checkKeyEvent(KeyEvent keyEvent) {
        if (keyEvent.getKeyCode() == KeyEvent.VK_F1) {
            log("F1 pressed: Open GUI.");
        } else if (keyEvent.getKeyCode() == KeyEvent.VK_F2) {
            log("F2 pressed");
            keyEvent.consume() // Now only F2 is consumed, by pressing F2, the stats tab won't open, however all over F-keys will still work.
        } else {
            log("Some key \"" + keyEvent.getKeyCode() + "\" has been pressed.");
        }
    }
};

BotMouseListener botMouseListener = new BotMouseListener() {
    @Override
    public void checkMouseEvent(MouseEvent mouseEvent) {
        if (mouseEvent.getButton() == 1) { 
            log("Left click");
        } else if (mouseEvent.getButton() == 2) {
            log("Right click");
        } else {
            log("Something click");
        }
    }
};

getBot().addMouseListener(botMouseListener); //Adds the MouseListener
getBot().addKeyListener(botKeyListener); //Adds the KeyListener

 

NOTE: You can check where a key/mouse button is pressed or released by using the paramString() method for the MouseEvent and the paramString() method for the KeyEvent.

 

Using resources

Spoiler

If you want to read certain files on your system e.g. txt files, you need to place it in the OSBot folder. Any other places will be denied by the OSBot client with the following message:

Quote

Blocked permission: ("java.io.FilePermission" "C:\Users\user\Desktop\osbot.txt" "read")

Here is a nice tutorial for using resources in the correct way..

Sources

Edits

Spoiler

15-09-2018: Updated based on Alek's feedback. Added resources paragraph.

 

Edited by feggit
update 15/09/2018
  • Like 7
  • Boge 1
Link to comment
Share on other sites

Just a few areas of improvement:

  • You're not consuming the events in the listeners, so that mouse data is being sent to the game. 
  • You do have access to the console for System.out.println
  • walkPath does generate a path if you do not provide it a list of positions, but it's a lot cheaper than generating a web walking path
  • The random number generator is already contained within method provider
  • ConditionalSleep information is misleading. The timeout is 10 seconds, the recheck is every 2 seconds. It doesn't sleep "up to 2 seconds", it sleeps exactly 2 seconds. Also don't waste your time putting random numbers into conditional sleep, you can't iterate a fraction of a cycle. For instance, 10000/2000 = 5. The ConditionalSleep will have 5 cycles, each cycle being 2 seconds on the recheck, for a maximum timeout of 10 seconds. Pretty simple math.
  • "if (getSkills().getDynamic(Skill.HITPOINTS) != getSkills().getStatic(Skill.HITPOINTS)) { //Checks if HP is full.", If you sara brew at full hp, it will say your hp is not full (which it is), use a < sign. 
  • Like 2
Link to comment
Share on other sites

3 hours ago, Alek said:

Just a few areas of improvement:

  • You're not consuming the events in the listeners, so that mouse data is being sent to the game. 
  • You do have access to the console for System.out.println
  • walkPath does generate a path if you do not provide it a list of positions, but it's a lot cheaper than generating a web walking path
  • The random number generator is already contained within method provider
  • ConditionalSleep information is misleading. The timeout is 10 seconds, the recheck is every 2 seconds. It doesn't sleep "up to 2 seconds", it sleeps exactly 2 seconds. Also don't waste your time putting random numbers into conditional sleep, you can't iterate a fraction of a cycle. For instance, 10000/2000 = 5. The ConditionalSleep will have 5 cycles, each cycle being 2 seconds on the recheck, for a maximum timeout of 10 seconds. Pretty simple math.
  • "if (getSkills().getDynamic(Skill.HITPOINTS) != getSkills().getStatic(Skill.HITPOINTS)) { //Checks if HP is full.", If you sara brew at full hp, it will say your hp is not full (which it is), use a < sign. 

Ok, thanks for the feedback. I will change my post according to these bullet points.

Link to comment
Share on other sites

Your GUI & lock point is debatable:

  • If you spent too much time in the GUI, you'll be logged out.
  • If you're unprepared in-game, you'd have to stop the script so you can ready yourself and then restart it.
  • If the GUI is more of a helper, then locking up the game renders the GUI pointless.

You don't have to block the onStart from ending; you can simply run checks onLoop to make sure your bot doesn't do anything until it has the information it needs from the GUI.

 

Also, you should include mention about script parameters, as they're very useful for power-users who don't want an expensive GUI to have to fiddle with. I wrote a tutorial about it here.

Link to comment
Share on other sites

  • 3 weeks later...
  • 9 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...