DylanSRT Posted September 28, 2018 Share Posted September 28, 2018 Basically, I am trying to use an item on another item with the same name in my inventory. Normally, I could just use slots to distinguish between the two, but the problem in this script is that it is not predetermined where the item will be. I tried using the code below. It works well when there is two different items as the first and second Item in the list. But, when they are the same item, it just clicks on the first item twice. I thought when you created a list of Items using a string, that it would be location specific as well. However, it seems to only get the name. My second thought was just to make a second list with the additional filter for itemIsSelected. But, then after thinking about it, the same thing will still happen if it just grabs the name. Any ideas? I will give you credit for helping with this portion if I do release this script. public void combineSpices(){ String [] spiceColors ={"Red","Yellow","Brown","Orange"}; for(String x:spiceColors){ while(combinableSpices(x)>1){ java.util.List<Item> vialsToCombine = Arrays.stream(getInventory().getItems()).filter(i -> i != null && i.nameContains(x+" spice (1)",x+" spice (2)",x+" spice (3)")).collect(Collectors.toList()); vialsToCombine.get(0).interact("Use"); vialsToCombine.get(1).interact("Use"); } } inventory.dropAll("Empty spice shaker"); } Quote Link to comment Share on other sites More sharing options...
Juggles Posted September 28, 2018 Share Posted September 28, 2018 Why not select the first item and just interact with the second? if no item selected select first item else use on other item Quote Link to comment Share on other sites More sharing options...
DylanSRT Posted September 28, 2018 Author Share Posted September 28, 2018 (edited) 16 minutes ago, Juggles said: Why not select the first item and just interact with the second? if no item selected select first item else use on other item Well that's what I am trying to do. The problem is that I can't distinguish the two items when they have the same names. All of the methods in the API (interact, getSlot, etc) always grab the "first item" matching an id or string. So what I really need is a way to output all of the slots for when there is more than one of the same item. To clarify, my list contains all of the 1dose , 2dose , 3dose spices. It works great until it runs into the case of 2 of the same amount of doses because then they have the same name. Edited September 28, 2018 by cooldoruk60 Quote Link to comment Share on other sites More sharing options...
Juggles Posted September 28, 2018 Share Posted September 28, 2018 36 minutes ago, cooldoruk60 said: Well that's what I am trying to do. The problem is that I can't distinguish the two items when they have the same names. All of the methods in the API (interact, getSlot, etc) always grab the "first item" matching an id or string. So what I really need is a way to output all of the slots for when there is more than one of the same item. To clarify, my list contains all of the 1dose , 2dose , 3dose spices. It works great until it runs into the case of 2 of the same amount of doses because then they have the same name. Oh I see what you mean. I've done something similar with grabbing the second closest NPC. You can try to filter out the first item Something like f->f.getName.equals(NAME) && f!=firstItem I don't have my IDE so i can't test right now but you can try that 1 Quote Link to comment Share on other sites More sharing options...
DylanSRT Posted September 28, 2018 Author Share Posted September 28, 2018 3 minutes ago, Juggles said: Oh I see what you mean. I've done something similar with grabbing the second closest NPC. You can try to filter out the first item Something like f->f.getName.equals(NAME) && f!=firstItem I don't have my IDE so i can't test right now but you can try that That's a good idea actually. It still won't be able to combine them if they have the same amount of doses, but at least I can skip them for now until I have a more permanent solution. Thanks Quote Link to comment Share on other sites More sharing options...
Juggles Posted September 28, 2018 Share Posted September 28, 2018 16 minutes ago, cooldoruk60 said: That's a good idea actually. It still won't be able to combine them if they have the same amount of doses, but at least I can skip them for now until I have a more permanent solution. Thanks int firstItem = getInventory().getSlotForNameThatContains(""); Item secondItem = inventory.getItemInSlot(firstItem+1); secondItem.interact("Use"); This would work if the second item is always in the next slot or you knew what slot it was in after Quote Link to comment Share on other sites More sharing options...
dogetrix Posted September 28, 2018 Share Posted September 28, 2018 Item first = null; for (Item i : getInventory().getItems()) { if (satisfiesStuff(i)) { if (first != null) { first.use(i); //forgot wtf piece of the api it was again and can't be bothered to look it up break; } else { first = i; } } } Quote Link to comment Share on other sites More sharing options...
FrostBug Posted September 28, 2018 Share Posted September 28, 2018 (edited) 43 minutes ago, dogetrix said: Item first = null; for (Item i : getInventory().getItems()) { if (satisfiesStuff(i)) { if (first != null) { first.use(i); //forgot wtf piece of the api it was again and can't be bothered to look it up break; } else { first = i; } } } Basically this^, but with slots instead of items, since Item does not contain slot data, if the 2 "different" items have the same name, it will still interact with the first occurence of the item twice. Something like this maybe: int[] slots = IntStream.range(0, Inventory.SIZE).filter(i -> isMatch(i, "Red spice")).toArray(); if(slots.length >= 2) { if(getInventory().interact(slots[0], "Use") && getInventory().isItemSelected()) { getInventory().interact(slots[1]); } } private boolean isMatch(int slot, String name) { Item item = getInventory().getItemInSlot(slot); return item != null && item.getName().startsWith(name) && !item.getName().endsWith("(4)"); } Edited September 28, 2018 by FrostBug 2 Quote Link to comment Share on other sites More sharing options...
DylanSRT Posted September 29, 2018 Author Share Posted September 29, 2018 Quote 15 hours ago, FrostBug said: Basically this^, but with slots instead of items, since Item does not contain slot data, if the 2 "different" items have the same name, it will still interact with the first occurence of the item twice. Something like this maybe: int[] slots = IntStream.range(0, Inventory.SIZE).filter(i -> isMatch(i, "Red spice")).toArray(); if(slots.length >= 2) { if(getInventory().interact(slots[0], "Use") && getInventory().isItemSelected()) { getInventory().interact(slots[1]); } } private boolean isMatch(int slot, String name) { Item item = getInventory().getItemInSlot(slot); return item != null && item.getName().startsWith(name) && !item.getName().endsWith("(4)"); } Brilliant Frost! I believe this will work. Thanks Quote Link to comment Share on other sites More sharing options...
dogetrix Posted September 29, 2018 Share Posted September 29, 2018 18 hours ago, FrostBug said: Basically this^, but with slots instead of items, since Item does not contain slot data, if the 2 "different" items have the same name, it will still interact with the first occurence of the item twice So if you have three items of the same type `getItems` will give you one object? Or is it that when you interact with the item it automatically selects the first one in the inventory? Either way it's dumb as hell. When you interact with an item you should expect to actually interact with that specific item. Quote Link to comment Share on other sites More sharing options...
DylanSRT Posted September 29, 2018 Author Share Posted September 29, 2018 3 hours ago, dogetrix said: So if you have three items of the same type `getItems` will give you one object? Or is it that when you interact with the item it automatically selects the first one in the inventory? Either way it's dumb as hell. When you interact with an item you should expect to actually interact with that specific item. It's the second one. But yes it is dumb. I thought that by specifying an Item object, it would have the state of it's location as well. But, when you call it using methods like interact or getSlot, it grabs only the first item. Quote Link to comment Share on other sites More sharing options...
liverare Posted September 29, 2018 Share Posted September 29, 2018 (edited) Following on from @FrostBug post, try this: @Override public int onLoop() throws InterruptedException { if (useItemWithAnotherItemOfTheSameName("Strength potion\\([1-3]\\)")) { stop(false); } return 250; } private boolean useItemWithAnotherItemOfTheSameName(String regex) { return IntStream.range(0, Inventory.SIZE) .filter(index -> { Item item = inventory.getItemInSlot(index); return item != null && item.getName().matches(regex); }) .limit(2) .allMatch(index -> inventory.interact(index, "Use")); } Strength potion\\([1-3]\\) will match Strength potion(1) Strength potion(2) Strength potion(3) The \\ used for \\( and \\) allow us to 'escape' the ( and ) characters, because in regex, they're special characters that need escaping if you wish to use them literally. The [1-3] will match the numbers 1, 2 and 3. Edited September 29, 2018 by liverare 1 Quote Link to comment Share on other sites More sharing options...
dreameo Posted September 29, 2018 Share Posted September 29, 2018 1 hour ago, liverare said: Following on from @FrostBug post, try this: @Override public int onLoop() throws InterruptedException { if (useItemWithAnotherItemOfTheSameName("Strength potion\\([1-3]\\)")) { stop(false); } return 250; } private boolean useItemWithAnotherItemOfTheSameName(String regex) { return IntStream.range(0, Inventory.SIZE) .filter(index -> { Item item = inventory.getItemInSlot(index); return item != null && item.getName().matches(regex); }) .limit(2) .allMatch(index -> inventory.interact(index, "Use")); } Strength potion\\([1-3]\\) will match Strength potion(1) Strength potion(2) Strength potion(3) The \\ used for \\( and \\) allow us to 'escape' the ( and ) characters, because in regex, they're special characters that need escaping if you wish to use them literally. The [1-3] will match the numbers 1, 2 and 3. You can use Pattern.quote to avoid having to worry about escape characters. 2 Quote Link to comment Share on other sites More sharing options...
DylanSRT Posted September 30, 2018 Author Share Posted September 30, 2018 @Juggles @FrostBug @liverare @dreameo I used a combination of your guy's suggestions and I also ended up moving away from the interact in the api and basically making my own interact method with hover+click. It turned out incredible though. I took a vid so you guys can see how insanely fast it is lol. And it never messes up. Never using interact for inventory interactions again .Thanks for all the help guys! If this script gets approved, I'll credit you all in the post. 2 1 Quote Link to comment Share on other sites More sharing options...