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
  • Drop all of a set of items


    century

    Recommended Posts

    edit: Please see the graduated version of this snippet here: https://dreambot.org/forums/index.php/topic/11715-customized-order-for-dropping-items/

     

    I ended up writing this code because the Inventory class doesn't have an option to drop all of a subset of items. If my character was barbarian fishing, and I wanted to drop 3 types of fish, I would have to do them one at a time, which seems extremely unnatural (it would drop all trout, then all salmon, followed by all sturgeon). The dropAllExcept() method won't suffice because the Inventory can't be predicted. What if the player has a valuable item? It would be dropped by this method. 

     

    So here's the method dropOnlyThese(). Simply give it an array of item id's, and it'll drop only those. Feedback is appreciated

    public void dropOnlyThese (Integer[] droppables) {
    		List<Item> inv = getInventory().all();
    		List<Integer> keepItems = inv.stream()
    					     .filter(i -> !Arrays.asList(droppables).contains(i.getID()))
    					     .map(i -> i.getID())
    				             .collect(Collectors.toList());
    		Integer[] itemIDs = keepItems.toArray(new Integer[keepItems.size()]);
    		getInventory().dropAllExcept(itemIDs);
    	
    	}
    

    Example usage:

    Integer[] droppables = {11328, 11330, 11332};
    dropOnlyThese(droppables);
    

    Unrelated: The method getClientSettings().getExactZoomValue() is not working. Are there any plans to fix this? If not, can I get git access to see if I can debug it?

     

    Also unrelated: Is there a way to set breakpoints in our code, and run in debug mode? Can I REPL the state of the program? (I hate debugging with log statements)

    Link to comment
    Share on other sites

    I ended up writing this code because the Inventory class doesn't have an option to drop all of a subset of items. If my character was barbarian fishing, and I wanted to drop 3 types of fish, I would have to do them one at a time, which seems extremely unnatural (it would drop all trout, then all salmon, followed by all sturgeon). The dropAllExcept() method won't suffice because the Inventory can't be predicted. What if the player has a valuable item? It would be dropped by this method. 

     

    So here's the method dropOnlyThese(). Simply give it an array of item id's, and it'll drop only those. Feedback is appreciated

    public void dropOnlyThese (Integer[] droppables) {
    		List<Item> inv = getInventory().all();
    		List<Integer> keepItems = inv.stream()
    					     .filter(i -> !Arrays.asList(droppables).contains(i.getID()))
    					     .map(i -> i.getID())
    				             .collect(Collectors.toList());
    		Integer[] itemIDs = keepItems.toArray(new Integer[keepItems.size()]);
    		getInventory().dropAllExcept(itemIDs);
    	
    	}
    

    Example usage:

    Integer[] droppables = {11328, 11330, 11332};
    dropOnlyThese(droppables);
    

    Unrelated: The method getClientSettings().getExactZoomValue() is not working. Are there any plans to fix this? If not, can I get git access to see if I can debug it?

     

    Also unrelated: Is there a way to set breakpoints in our code, and run in debug mode? Can I REPL the state of the program? (I hate debugging with log statements)

     

    Cool snippet, thanks for sharing. I think you may be able to do this with the API though. Have you tried using a filter with `getInventory().dropAll()`? Would something like the code below do what you're wanting?

    getInventory().dropAll((item) -> item != null && (item.getID() == 11328 || item.getID() == 11330 || item.getID() == 11332));
    
    
    Link to comment
    Share on other sites

     

    Cool snippet, thanks for sharing. I think you may be able to do this with the API though. Have you tried using a filter with `getInventory().dropAll()`? Would something like the code below do what you're wanting?

    getInventory().dropAll((item) -> item != null && (item.getID() == 11328 || item.getID() == 11330 || item.getID() == 11332));
    
    

     

    I just tried your implementation, and it works exactly as intended. Would you kindly explain what's going on here? I have a lack of understanding. The API documentation for dropAll() has three overloaded methods, which takes a) nothing, B) an integer ID, or c) the String name of the item. What is this black magic that you've done?

    Link to comment
    Share on other sites

    I just tried your implementation, and it works exactly as intended. Would you kindly explain what's going on here? I have a lack of understanding. The API documentation for dropAll() has three overloaded methods, which takes a) nothing, B) an integer ID, or c) the String name of the item. What is this black magic that you've done?

    Awesome! To explain whats going on here, the first thing to know is that we're using a lambda expression. The lambda expression here is essentially an anonymous function that will be called on each inventory item slot. The expression must evaluate to a boolean value. If that boolean value that the expression evaluates to is true, then in this case it drops the item. If the boolean value that the expression evaluates to is false, then it does not drop the item. So to break the code down, here is whats happening.

     

    First note that we are accepting a parameter that we named "item" (as represented by "dropAll((item) -> ..."). The expression will be evaluated one time for each inventory item slot, so by the time the line of code is done executing we will have passed each inventory item slot through this expression.

     

    Next we are null checking the item before doing anything else (as represented by "dropAll((item) -> item != null && ..."). The reason for this is that since each inventory item slot will be passed through the expression, any empty item slot will be null. If we do not null check the item and there is an empty slot then we will end up getting a NullPointerException.

     

    Last we are checking if the item id matches any of the ids of the items we want to drop (as represented by "dropAll((item) -> item != null && (item.getID() == 1351 || item.getID() == 555 || item.getID() == 1059));"). 

     

    Here are a couple of scenarios that may help with understanding how its working.

     

    1. The item passed through the expression is an empty item slot in our inventory. What happens is the null check fails since its an empty slot (because it does == null). Since java && use short-circuit expression evaluation, if the left side of the && expression is false, Java gives up and calls the whole expression false. This means the code on the right side of the && won't even be run if the left side of it fails. Since this expression evaluated to false, we will not drop this item.

     

    2. The item passed through the expression is a valid item, but its ID does not match one of the three we're looking for. This item would pass the null check on the left side of the &&, but it would fail the right side since its id does not match any of the three we're checking it against. Since we passed the left side of the && but failed the right side our expression has evaluated to essentially "true && false", which further evaluates to just "false". Since this expression evaluated to false, we will not drop this item.

     

    3. The item passed through the expression is a valid item, and its id does match one of the three we're looking for. The item would pass the null check on the left side of the && since it is a valid item. It would also pass the id check on the right side of the && since its id does match one of the three we're checking for. This expression would evaluate to "true && (false || false || true)" (assuming its ID matched the last one we checked for), which further evaluates to "(true && true)", which further evaluates to just "true". Since this expression evaluated to true, we will drop this item.

     

    I hope that gives you a fairly comprehensive understanding of whats going on with the code. Filters are extremely useful, and can be used with a lot of the API. Let me know if you still have any questions!

    Link to comment
    Share on other sites

    Awesome! To explain whats going on here, the first thing to know is that we're using a lambda expression. The lambda expression here is essentially an anonymous function that will be called on each inventory item slot. The expression must evaluate to a boolean value. If that boolean value that the expression evaluates to is true, then in this case it drops the item. If the boolean value that the expression evaluates to is false, then it does not drop the item. So to break the code down, here is whats happening.

     

    First note that we are accepting a parameter that we named "item" (as represented by "dropAll((item) -> ..."). The expression will be evaluated one time for each inventory item slot, so by the time the line of code is done executing we will have passed each inventory item slot through this expression.

     

    Next we are null checking the item before doing anything else (as represented by "dropAll((item) -> item != null && ..."). The reason for this is that since each inventory item slot will be passed through the expression, any empty item slot will be null. If we do not null check the item and there is an empty slot then we will end up getting a NullPointerException.

     

    Last we are checking if the item id matches any of the ids of the items we want to drop (as represented by "dropAll((item) -> item != null && (item.getID() == 1351 || item.getID() == 555 || item.getID() == 1059));"). 

     

    Here are a couple of scenarios that may help with understanding how its working.

     

    1. The item passed through the expression is an empty item slot in our inventory. What happens is the null check fails since its an empty slot (because it does == null). Since java && use short-circuit expression evaluation, if the left side of the && expression is false, Java gives up and calls the whole expression false. This means the code on the right side of the && won't even be run if the left side of it fails. Since this expression evaluated to false, we will not drop this item.

     

    2. The item passed through the expression is a valid item, but its ID does not match one of the three we're looking for. This item would pass the null check on the left side of the &&, but it would fail the right side since its id does not match any of the three we're checking it against. Since we passed the left side of the && but failed the right side our expression has evaluated to essentially "true && false", which further evaluates to just "false". Since this expression evaluated to false, we will not drop this item.

     

    3. The item passed through the expression is a valid item, and its id does match one of the three we're looking for. The item would pass the null check on the left side of the && since it is a valid item. It would also pass the id check on the right side of the && since its id does match one of the three we're checking for. This expression would evaluate to "true && (false || false || true)" (assuming its ID matched the last one we checked for), which further evaluates to "(true && true)", which further evaluates to just "true". Since this expression evaluated to true, we will drop this item.

     

    I hope that gives you a fairly comprehensive understanding of whats going on with the code. Filters are extremely useful, and can be used with a lot of the API. Let me know if you still have any questions!

     

    Thanks so much for the explanation. You really went the extra mile, and I appreciate it. All of the stars seem to align, except for one point:

     

    Can you call someMethod((x) -> someBooleanExpression) with any iterative method? The Inventory class implements the java.lang.Iterable<Item> interface; Is this why we're able to filter it using a lambda expression (anonymous method)? If so, this is absolutely brilliant and will make my code significantly more eloquent. 

     

    Unrelated: Is there a way to set breakpoints and investigate the state of a running DreamBot script?

    Link to comment
    Share on other sites

    Thanks so much for the explanation. You really went the extra mile, and I appreciate it. All of the stars seem to align, except for one point:

     

    Can you call someMethod((x) -> someBooleanExpression) with any iterative method? The Inventory class implements the java.lang.Iterable<Item> interface; Is this why we're able to filter it using a lambda expression (anonymous method)? If so, this is absolutely brilliant and will make my code significantly more eloquent. 

     

    Unrelated: Is there a way to set breakpoints and investigate the state of a running DreamBot script?

    You're wondering why you dont see this

    public boolean dropAll(Filter<Item> filter)

    Probably because the javadocs are outdated.

     

     

    Also you are able to setup a remote debugging session.

     

    I have a DreamBot.bat that launches dreambot with a socket listening for remote connection. 

    start /B java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=12345 -jar C:\Users\slasso\DreamBot\BotData\client.jar

    Then in Eclipse/IntelliJ you setup a remote application debug on the same port 12345. Once DreamBot launches you can start the debug. Set your breakpoints and now run your script.

     

    I have a tutorial on it https://dreambot.org/forums/index.php/topic/5272-how-to-remote-debug-your-scripts/ that has been buried away for some time now

    Link to comment
    Share on other sites

    You're wondering why you dont see this

    public boolean dropAll(Filter<Item> filter)

    Probably because the javadocs are outdated.

     

     

    Also you are able to setup a remote debugging session.

     

    I have a DreamBot.bat that launches dreambot with a socket listening for remote connection. 

    start /B java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=12345 -jar C:\Users\slasso\DreamBot\BotData\client.jar

    Then in Eclipse/IntelliJ you setup a remote application debug on the same port 12345. Once DreamBot launches you can start the debug. Set your breakpoints and now run your script.

     

    I have a tutorial on it https://dreambot.org/forums/index.php/topic/5272-how-to-remote-debug-your-scripts/ that has been buried away for some time now

     

    I just finished reading your debugging guide. It's excellent!

     

    As for the JavaDocs, how can I make contributions? I'd be more than happy to help maintain the documentation if it'll help people avoid the same confusion that I've faced.

    Link to comment
    Share on other sites

    I just finished reading your debugging guide. It's excellent!

     

    As for the JavaDocs, how can I make contributions? I'd be more than happy to help maintain the documentation if it'll help people avoid the same confusion that I've faced.

    Only the devs add javadocs. Some methods aren't javadoc'd and DreamBot 3 is being developed so I don't think they are spending any time commenting methods

    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.