Jump to content
Frequently Asked Questions
  • Are you not able to open the client? Try following our getting started guide
  • Still not working? Try downloading and running JarFix
  • Help! My bot doesn't do anything! Enable fresh start in client settings and restart the client
  • How to purchase with PayPal/OSRS/Crypto gold? You can purchase vouchers from other users
  • PlayerSettings : Bitwise operations and bitmasks


    Articron

    Recommended Posts

    PlayerSettings class: PlayerSettings

     

    AUTHOR NOTE: This tutorial goes somewhat indepth, but I tried my best to break down every single aspect to a much simpler concept.

    Keep in mind that this only handles the things you could utilise in scripting, there is lots more to learn about within this field when talking from a general Java perspective. The first few chapters try to give you a basic background on bitwise operations, so that things get easier when applying it to a scripting example.

     

    Level: Intermediate

    Difficulty: 5/10

     

    Tutorial goals

    • The reader can explain in his own words what PlayerSettings are, and in what context they can prove useful.
    • The reader can explain the underlying structure of what an "32-bit integer" CAN represent in this tutorial's context.
    • The reader can utilise bitwise operations to read/manipulate "bit blocks", which he/she can use within script logic.
    • The reader can utilise Bitmasks to differentiate between multiple "bit blocks", which he/she can use within script logic.

    1. What PlayerSettings are

     

     

    When you start the Dreambot client, it automatically starts a new Runescape client instance. This RS client keeps alot of information and data about you (The Player) or about the client itself. This data is saved and kept track of in the client under what is defined as "PlayerSettings" in the Dreambot API. 


    As you can imagine, there's an insane amount of things the client has to keep track of. This means there would be ALOT of variables.

    Jagex found a way to "compress" these variables. They "compressed" multiple pieces of data within 1 integer. It just so happens these multi-purpose integers can be retrieved with the PlayerSettings class.

     

    Things like wether or not your run mode is enabled, wether or not you're logged in, Grand Exchange progress, Tutorial island progress,... Is all saved within these PlayerSettings. 

     

    A playerSetting has an ID, this makes it unique. Every PlayerSetting has an integer linked to them.

    We can call upon a certain setting with PlayerSettings#getConfig(int id). The int that is returned is the integer linked to that specific PlayerSetting that carries the data we are interested in.

     

    For example: The new deadman interface where you can save/protect certain skills, is all being kept track of with a single integer. 

     

    We can utilise these PlayerSettings to our advantage in scripts. For the example above: Instead of checking every WidgetChild for its colour/text/whatever, we could just read the PlayerSetting and know which skills we are saving in deadman, without the need of opening the interface itself. 

     

    It's a good scripting ethic to utilise these PlayerSettings. On other people's source codes across several botting communities I've seen alot of scripters not taking advantage of this feature, even though it would improve their script.

     

     

     

    2. PlayerSettings are saved with a 32-bit integer

     

     

    What do I mean with a "32-bit" integer?

    As you know the integer has certain boundaries: Integer.MAX_VALUE and Integer.MIN_VALUE.

     

    What we do in programming:

    private int number = 5; // DECIMAL
    

    the variable "number" is given a DECIMAL format. However, there are also other formats, like a BINARY format:

    private int number = 0b00000000000000000000000000000101; // BINARY (could be 0b101, added 32 bits for clarity)
    

    We use the binary literal 0b to specify we are dealing with a binary format. With "binary literal", I basically mean the 0b prefix.

     

    Both variables above are equal to the number 5. Test it out:

    public static void main(String... args) 
    {
        System.out.println(5);
        System.out.println(0b00000000000000000000000000000101);
    }
    // output
    // 5
    // 5

    It's in this binary form that we can manipulate/read certain parts of the "bit-chain", (the collection of 0's and 1's). And it is in the binary format where PlayerSettings serve their purpose.

     

     

     

    3. How to form a binary format

     

     

    If you got this far, good job. This might sound Arabic to you, which is good to hear! This is because Arabic writing has to be read from right to left.

    You will understand what I mean by that momentarily.

     

    So, let's take our binary number 5 again:

    private int number = 0b00000000000000000000000000000101; // BINARY (could be 0b101, added 32 bits for clarity)
    

    Each 0 and 1 is called a "bit". In binary, a bit can only be 0 or 1. In total, you have 32 bits in there (excluding the 0b literal), hence why integers are 32-bit. (Longs for example are 64-bit).

     

    Let's just take the 32 bits, and look at nothing else for a second.

    00000000000000000000000000000101
    

    Each of these bits have a "slot id". The slots are ordered from right to left, And increment by the power of 2 each time.

     

    Here is a colourful representation of what I mean:

     

    00000000000000000000000000000101
    Slot 1
    Slot 2
    Slot 4
    Slot 8
    Slot 16

     

    Note: if you expected me to give a colour to each and all 32 bits, you're dizzy af in the head

     

    Now let's take a look at which slots have the bit value 1:

     

    Slot 1 has a bit value of 1

    Slot 4 has a bit value of 1

     

    Now hold on! Can you see it before I tell you? Remember that this binary chain is equal to 5.

     

    1 + 4 = 5.

     

     

    things-that-blew-your-mind-when-you-were

     

     

     

    Now here's another mind blower, what if all bits were 1?

    0b11111111111111111111111111111111 

    ^ The above bit number is equal to Integer.MAX_VALUE. There is no way we could add more 1's, because then it wouldn't have 32 bits anymore!

     

     

     

    4. Shifting the bits

     

     

    Shifting the bits is done with a bitwise operation. In scripting, the most common used is the signed right shift.

     

    The signed right shift has an operator. This operator is >>.
     

    Example:

    private int number = Y >> X;
    

    Shifting bits does as it implies: It shoves the bitchain of Y to the right X amount of times.

     

    Example:

    0b00000000000000000000000000010000 >> 2 = 0b00000000000000000000000000000100
    

    Did you see what happened there? The 1-bit got shifted to the right twice. 

     

     

    Q: But what happens if the 1-bit is already on the right?

     

    A: It gets removed, and a 0 is added to the left of the chain.

     

    Example:

    0b00000000000000000000000000000001 >> 1 = 0b0000000000000000000000000000000
    

    NOTE: ANY 1-bit that falls off the chain because of a shift, gets removed and replaced with an 0 on the left!

     

    Example:

    0b00000000000000000000000010000000 >> 9 = 0b0000000000000000000000000000000 

    In order to evaluate your understanding, put this in your IDE, but DONT run it yet:

    public static void main(String... args) 
    {
       System.out.println(7 >> 2); 
    } 

    Try to predict what value will be given when you run this.

    TIP: write down the binary chain of 7 down first, it will make things much easier.

     

    Answer can be found below:

     

     

    ANSWER = 1

     

    7 >> 2

    7 = 0b00000000000000000000000000000111

    SHIFT TO THE RIGHT 2 TIMES

    0b00000000000000000000000000000001 = 1

     

     

     

     

     

    5. Masking the shifted bits

     

     

    Author note: This part is rather irritating to explain, apologies if it is a bit sloppy.

     

    Masking part of a bitchain is part of telling your program on what bits to focus on. A bitmask has the & operator. It is officially called the AND operator.

     

    Bitmasks can be made in either format, but for the sake of simplicity we will keep it a binary format.

     

    Example:

    private int number = 7 >> 2 & 0b1;
    

    The number: 7

    The shift: 2

    The mask: 0b1 

     

    Notice how the mask has only 1 digit (excluding the binary literal) ? This means that your application will only look at the first bit slot.

    The output = 1.

     

    Now let's switch it up to have a bigger example:

    0b00000000000010000100100010000010 >> 11 & 0b1111;

    So first things first, we shift that bitchain 11 times to the right:

    0b00000000000000000000000100001001
    

    Now all that is left is our mask: 0b1111. 

    We want to only look at first four bit slots. This is why our mask is 0b1111 (4 times a 1).

     

    Visual representation:

     

    0b00000000000000000000000100001001

    0b1111 mask

     

    All the other bits in black, are not being looked at by your application anymore. The 1-bit that is black, will not be counted when applying the bitmask.

     

    This means that "1001" is left. 

     

    We do the math:

     

    1 + 8 = 9.

    0b00000000000010000100100010000010 >> 11 & 0b1111
    = 9
    

     

     

     

    6. Applying our new knowledge to scripting

    Credits to @@Eclipseop for writing a practical addition to this tutorial.

    It can be found on this post: https://dreambot.org/forums/index.php/topic/3911-playersettings-bitwise-operations-and-bitmasks/?p=58041

    Link to comment
    Share on other sites

     

    I like to think mine is a little bit more broken down into bits (pun intended) & pieces.

     

    I checked his post, and it doesn't seem to have much value for someone who doesn't know anything about the topic.

    He also doesn't use bitshifts at all in his example, only bitmasks ;)

    Link to comment
    Share on other sites

    I like to think mine is a little bit more broken down into bits (pun intended) & pieces.

     

    I checked his post, and it doesn't seem to have much value for someone who doesn't know anything about the topic.

    He also doesn't use bitshifts at all in his example, only bitmasks ;)

    im js

    Link to comment
    Share on other sites

    • 9 months later...

    Gonna make an addition since it's been a while and there has been some talk in chat about how to apply this to player settings.

    Let's take runecrafting pouches for an example, and how to make methods for checking if said pouch is full. The player setting 720 refers to the ingame data that is stored regarding the players pouches.

    When only the small pouch is full, the setting reads 2, only med pouch is 8, and only full is 32;

    Binary counterparts:
    0b00000000000000000000000000000010 <- 2 aka small

    0b00000000000000000000000000001000 <- 8 aka medium

    0b00000000000000000000000000100000 <- 32 aka large

     

    Now lets say the setting returns 34, so the binary is:

    0b00000000000000000000000000100010

     

    By this we can tell that both the large and small pouches are full. Whenever the small pouch is full, the 2nd bit is set to 1, and whenever the large pouch is full, the 6th bit is set to 1.

    So how do we use the bitwise ops?

    Lets take a look at isMediumPouchFull:

    public static final int MEDIUM_POUCH = 0b1000;
    
    private boolean isMediumPouchFull() {
    	return (Settings.get(720) & MEDIUM_POUCH) == MEDIUM_POUCH;
    }
    

    the mask (&) makes it so we only read the bits we indicate, so since we pass 0b1000 (8) it checks for that bits, and returns the decimal equivalent for the matched bits, example: 

     

    10 = 0b1010;

    2 = 0b10;

     

    10 & 2 would return only 0b10, since that is the only bits that are equal to 1 and are the same, so then once we mask the to the expected amount, we simply check if the returned value is equal to the expected.

    Link to comment
    Share on other sites

    Archived

    This topic is now archived and is closed to further replies.

    ×
    ×
    • Create New...

    Important Information

    We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.