century 26 Share Posted August 31, 2017 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 More sharing options...
distraction 61 Share Posted August 31, 2017 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 More sharing options...
century 26 Author Share Posted August 31, 2017 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, 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 More sharing options...
distraction 61 Share Posted August 31, 2017 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, 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 More sharing options...
century 26 Author Share Posted August 31, 2017 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 More sharing options...
slasso 27 Share Posted August 31, 2017 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 More sharing options...
century 26 Author Share Posted August 31, 2017 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 More sharing options...
slasso 27 Share Posted August 31, 2017 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 More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.