Jump to content

How to drop items 3x faster than API dropping methods [Video]


DylanSRT

Recommended Posts

Edit:  I made this thread more so as awareness that the API drop methods suck atm (at least on mirror mode) and that scripters can easily make faster dropping methods. I'm clearly not the most experienced scripter here and I know most of you could write this code 10 times better (I'm actually hoping someone does and updates the API) lol.

 With regards to an understandable concern about this being "botlike" behavior, I can assure you that I have used this on my scripts for many hours without any problems. Also, if you consider the mousekey method which many players use: they use one key to click and one key to move down a certain number of pixels. My code has a 20 pixel range whereas they would be on the same pixel every time. I highly doubt that Jagex uses dropping behaviors as a bot detection method. That being said, if you're scared and would rather drop items like my grandma, then the API is there for you! I honestly think the slowness is more suspect then the speed of my bot which I would say is around average for humans using shift drop.

 

The three derivations for this method should pretty much cover any dropping requirements you might have :

  1. Drop All - Drops everything in your inventory like the video. No input arguments necessary.
  2. Drop All w/ input - Drops all of an item in your inventory whose string name or integer id are used as input. If an array is used as input here, all of it's elements will be dropped and everything else retained
  3. Drop All Except w/ Input - Drops everything besides the item in your inventory whose string name or integer id are used as input. If an array is used as input here, all of it's elements will be retained and everything else dropped

I'll try to annotate it a bit since I know some of you want to learn more, but for most of you, this is really some pretty basic stuff. 

First, make sure to bring in these two methods as they are used in all three instances:

Spoiler

	private int mouseXSlot(int slot){
        slot=slot+1;
        if (slot ==1||slot==5||slot==9||slot==13||slot==17||slot==21||slot==25){
            return random(565,585);
        }else if(slot==2||slot==6||slot==10||slot==14||slot==18||slot==22||slot==26){
            return random(610,630);
        }else if(slot==3||slot==7||slot==11||slot==15||slot==19||slot==23||slot==27){
            return random(655,675);
        }else{
            return random(695,715);
        }
    }

    private int mouseYSlot(int slot){
        slot=slot+1;
        if (slot>=1&&slot<=4){
            return random(215,235);
        }else if(slot>=5&&slot<=8){
            return random(255,275);
        }else if(slot>=9&&slot<=12){
            return random(290,310);
        }else if(slot>=13&&slot<=16){
            return random(330,350);
        }else if(slot>=17&&slot<=20){
            return random(365,385);
        }else if(slot>=21&&slot<=24){
            return random(400,420);
        }else{
            return 440;
        }
    }

 

What these methods are doing is allowing us to input a slot to interact with and receive the coordinates for the mouse to go to. Yes, I know you can make the mouse go to certain slots without specifically providing coordinates. But this requires the invoking of what I call middleman methods and slows down the script. It's much faster to just give your mouse a direct location to go to without requiring any other info. You will notice I left the coordinates as a range using random because some people don't like clicking the same exact pixel over and over. Although I personally don't think it has any affect on bot detection.

1. Drop All

Spoiler

 int[] slots = IntStream.range(0, Inventory.SIZE).filter(j -> getInventory().getItemInSlot(j)!=null).toArray();
//Creates an array of the slots in your iventory which pass an Item null check, which means there is an item in that slot.
    keyboard.pressKey(KeyEvent.VK_SHIFT); //press the shift key to allow for left click dropping, never put a sleep between keyboard code
            for (int i=0;i<=slots.length-1;i++){  //This for loop will allow us to retrieve every slot individually from the array we created above
                mouse.click(mouseXSlot(slots[i]),mouseYSlot(slots[i]),false); //retrieve the coordinates for this slot using our methods and left click with a false boolean
            }
      keyboard.releaseKey(KeyEvent.VK_SHIFT);
//it's really that simple

 

2. Drop All w/ Inputs

Spoiler

String [] itemsToDrop ={item1,item2,item3,...} //Create an array of the string names of the items you want to drop
                               
                               int[] slots = IntStream.range(0, Inventory.SIZE).filter(j -> getInventory().getItemInSlot(j)!=null &&
                               getInventory().getItemInSlot(j).nameContains(itemsToDrop)).toArray();
                               
                               //the filter will now only grab slots for items which match one of the names in the array, in addition to the null check
                        //if you want to use an integer array of ids instead, change the nameContains method to idContains
                        //rest is exactly the same
                        
                  keyboard.pressKey(KeyEvent.VK_SHIFT); //press the shift key to allow for left click dropping, never put a sleep between keyboard code
            for (int i=0;i<=slots.length-1;i++){  //This for loop will allow us to retrieve every slot individually from the array we created above
                mouse.click(mouseXSlot(slots[i]),mouseYSlot(slots[i]),false); //retrieve the coordinates for this slot using our methods and left click with a false boolean
            }
      keyboard.releaseKey(KeyEvent.VK_SHIFT);

                        
                        

 

3. Drop All Except w/ Inputs

Spoiler

String [] itemsToRetain ={item1,item2,item3,...} //Create an array of the string names of the items you want to keep
                               
                               int[] slots = IntStream.range(0, Inventory.SIZE).filter(j -> getInventory().getItemInSlot(j)!=null &&
                               getInventory().getItemInSlot(j).!nameContains(itemsToRetain)).toArray();
                               
                               //the filter will now only grab slots for items which DO NOT match one of the names in the array, in addition to the null check
                        //if you want to use an integer array of ids instead, change the nameContains method to idContains
                        //rest is exactly the same
                        
      keyboard.pressKey(KeyEvent.VK_SHIFT); //press the shift key to allow for left click dropping, never put a sleep between keyboard code
            for (int i=0;i<=slots.length-1;i++){  //This for loop will allow us to retrieve every slot individually from the array we created above
                mouse.click(mouseXSlot(slots[i]),mouseYSlot(slots[i]),false); //retrieve the coordinates for this slot using our methods and left click with a false boolean
            }
      keyboard.releaseKey(KeyEvent.VK_SHIFT);

 

Please don't leave any comments saying "you didn't use any sleeps, you're a bad scripter". There are many instances when conditional sleeps are necessary, but this method does not require it, as you should be able to tell from the video. Just as sleeping has it's benefits when it is necessary, it has an equally negative impact on speed when it is not necessary. I've ran versions of this code in my script thousands of times and have never once had any issues.

Edited by cooldoruk60
  • Like 1
Link to comment
Share on other sites

@Juggles

 

I don't think so, I've been using it for a while. But I can add some delay to it. Do you really think it needs to be as slow as what's in the API? As long as you are not doing something like only dropping, you should be fine. I forget who's script it is but the AIO thiever that many people use has a dropper just like this which can sort through seeds. It's the most unhuman thing ever, but I got 90-99 at farmers no problem.

I don't know about you but when I am playing legit my drops look a lot more like my script than the other one. Especially with using shift drop with mousekeys, a human could actually go much faster than this in a vertical line imo

 

Edited by cooldoruk60
Link to comment
Share on other sites

25 minutes ago, cooldoruk60 said:

@Juggles

 

I don't think so, I've been using it for a while. But I can add some delay to it. Do you really think it needs to be as slow as what's in the API? As long as you are not doing something like only dropping, you should be fine. I forget who's script it is but the AIO thiever that many people use has a dropper just like this which can sort through seeds. It's the most unhuman thing ever, but I got 90-99 at farmers no problem.

I don't know about you but when I am playing legit my drops look a lot more like my script than the other one. Especially with using shift drop with mousekeys, a human could actually go much faster than this in a vertical line imo

 

Maybe it's cause I'm more of a controller guy but I click pretty slow. A little faster than the API but way slower than your bot ?

Link to comment
Share on other sites

7 minutes ago, Juggles said:

Maybe it's cause I'm more of a controller guy but I click pretty slow. A little faster than the API but way slower than your bot ?

Check this vid out: basically what a lot of legit players do is set it up so that they press one key to click, and one key to go down a certain amount of pixels. So it's actually a lot more botlike than this script. I also use a 20 pixel range whereas they would be on the same pixel. I would think that Jagex would not use this sort of behavior for bot detection. go to around 2:30 and you'll see how fast it is. And that was before they even introduced shift drop, so its a lot more widespread now.

 

Link to comment
Share on other sites

  • DylanSRT changed the title to How to drop items 3x faster than API dropping methods [Video]
14 hours ago, Alek said:

I don't think that's inventory dropAll method. Assuming shift-clicking is enabled, the osbot version actually drops it even faster than the one on the right. Also did you do one with shift clicking and the other without?

I promise you it is mate. I remember it being much faster too. But it sucks now to be quite blunt. Maybe it's only mirror mode? I don't touch client injection with a stick so I can't tell you if it's the same on there. Yes, I intentionally did that to show that even without shift drop I can go much faster. if you want I can shoot you over a class file and you can try the dropAll method yourself

Edited by cooldoruk60
Link to comment
Share on other sites

18 minutes ago, cooldoruk60 said:

Just looking at it though, you can kind of see that it's having something go wrong with the code. It's got that vibration kind of look if you know what I mean. Possibly some sort of exception

What does this mean..?

Also, just a note, for every single item, you press shift, rapidly drop it, then unshift. You do the same thing 28 times, each in the span of less than 50ms. 

Edited by Team Cape
Link to comment
Share on other sites

12 minutes ago, Team Cape said:

What does this mean..?

Also, just a note, for every single item, you press shift, rapidly drop it, then unshift. You do the same thing 28 times, each in the span of less than 50ms. 

yeah i suppose I could put the key press before the for loop ?but usually when something is already working as well as I wanted, I don't change anything else. I think I read somewhere that you shouldn't put too many actions within one key press/release. I know for some reason you cannot sleep during a key press as well. 

I don't know why I said vibration lol. I meant that it has different amounts of time between each drop and each just looks a little jerky. Like maybe it is requesting some information that is not available.

Edited by cooldoruk60
Link to comment
Share on other sites

@Team Cape

Wait I misunderstood what you said. If you are implying that my for loop is not working as I intended, I suggest you re-look at the stream I am using. I know for a fact there is only one loop per drop because i've ran it with log outputs before.

Also the length of the array from the stream is not necessarily 28 . If I had 1 item only in my inv, the length would be 1. 

Edited by cooldoruk60
Link to comment
Share on other sites

7 hours ago, cooldoruk60 said:

I promise you it is mate. I remember it being much faster too. But it sucks now to be quite blunt. Maybe it's only mirror mode? I don't touch client injection with a stick so I can't tell you if it's the same on there. Yes, I intentionally did that to show that even without shift drop I can go much faster. if you want I can shoot you over a class file and you can try the dropAll method yourself

I dont know about dropping with mirror mode but when i tried to open item packs using mirror mode it is incredibly slow as well.

Link to comment
Share on other sites

With each iteration of your for loop, you're pressing and releasing the [shift] key, which is suspect.

There already is InventorySlotDestination which calculates the X and Y for inventory slots. However, I'd always advise to learn how that stuff does what it does, as opposed to just using it. You could build up your inventory dropping function into your own API, and perhaps have the initialiseModule generate up a bunch of Rectangles in an array, then pick whichever you need using the slot.

As for your code, it's pretty...spaghetti. I would recommend you break your processes up into separate routines:

  • Two routines to get the row and column indices for the inventory slot.
  • Two routines to convert row and column indices into X and Y coordination points.
  • Then a few helper routines to help break down the analysis and interactions, just to make the main function dropAll look cleaner.
  • Finally, a dropAll function.

The result could look something like this:
 

	@Override
	public int onLoop() {
		
		// ... 
		
		if (dropAll("Tuna", "Salmon", "Herring")) {
			
			// We successfully dropped junk items
		}
		
		if (dropAll()) {
			
			// We successfully dropped all items
		}
		
		// ... 
	}
	
	public boolean dropAll(String... names) {
		
		boolean success = false;
		
		keyboard.pressKey(KeyEvent.VK_SHIFT);
		
		IntStream.range(1, Inventory.SIZE + 1)
			.filter(slot -> isItemPresent(slot, names))
			.forEach(this::leftClickInventorySlot);
		
		keyboard.releaseKey(KeyEvent.VK_SHIFT);
		
		if (names != null) {
			
			success = !inventory.contains(names);
			
		} else {
			success = inventory.isEmpty();
		}
		
		return success;
	}

Then, you'd have all the other code put into a separate class and perhaps wrapped as its own API:
 

	// Helper functions listed below

	private boolean leftClickInventorySlot(int slot) {
		return mouse.click(
				getXPointForInventoryColumn(slot),
				getYPointForInventoryRow(slot),
				false);
	}
	
	private boolean isItemPresent(int slot, String... names) {
		Item item = inventory.getItemInSlot(slot);
		return item != null && (names == null || item.nameContains(names));
	}
	
	// Static helper functions listed below
	
	private static int getInventoryRow(int slot) {
		return (slot - 1) / 4;
	}

	private static int getInventoryColumn(int slot) {
		return (slot - 1) % 4;
	}

	private static int getYPointForInventoryRow(int slot) {
		
		int min;
		int max;
		int row = getInventoryRow(slot);

		switch (row) {
		case 0:
			min = 215;
			max = 235;
			break;
		case 1:
			min = 255;
			max = 275;
			break;
		case 2:
			min = 290;
			max = 310;
			break;
		case 3:
			min = 330;
			max = 350;
			break;
		case 4:
			min = 365;
			max = 385;
			break;
		case 5:
			min = 400;
			max = 420;
			break;
		default: // 6 is max
			min = 440;
			max = 445;
			break;
		}

		return random(min, max);
	}
	
	private static int getXPointForInventoryColumn(int slot) {
		
		int min;
		int max;
		int column = getInventoryColumn(slot);
		
		switch (column) {
		case 0:
			min = 565;
			max = 585;
			break;
		case 1:
			min = 610;
			max = 630;
			break;
		case 2:
			min = 655;
			max = 675;
			break;
		default: // 3 is max
			min = 695;
			max = 715;
			break;
		}
		
		return random(min, max);
	}

 

Edited by liverare
  • Like 2
Link to comment
Share on other sites

@liverare

This was intended to be a snippet lol, not a script on it's own. If scripter doesn't know how to use this in their code, they're probably not going to be able to anyways.

That being said though, I am too used to making scripts for myself. I need to learn to package things better and will definitely use your advice. Thanks

Also, I made this thread more so as awareness that the API drop function sucks atm and that scripters can easily make faster dropping methods. I'm clearly not the most experienced scripter here and I know most of you could write this code 10 times better (I'm actually hoping someone does and updates the API) lol.

Edited by cooldoruk60
  • Like 1
Link to comment
Share on other sites

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