Added sorting on the item overlay, items now appear in the order that they'll be picked up (#320)

Changed item menu sorting:
  Hidden items now appear at the bottom of the menu, so that hidden items don't get picked up over lower value non-hidden items

  Added a config option to put hidden items below "Walk here"
    this option makes it so that you can't accidentally pick up hidden items

  Added a config option to sort by GE value
    this option means that you'll always pick up highest GE value items first with left click
    this option also sorts the overlay by GE value
This commit is contained in:
James
2019-05-20 13:31:20 -07:00
committed by Kyleeld
parent a327cc2a42
commit 68fa0ef253
3 changed files with 1793 additions and 1673 deletions

View File

@@ -436,4 +436,26 @@ public interface GroundItemsConfig extends Config
{ {
return TimerDisplayMode.HOTKEY_PRESSED; return TimerDisplayMode.HOTKEY_PRESSED;
} }
@ConfigItem(
keyName = "sortByGEPrice",
name = "Sort by GE price",
description = "Sorts ground items by GE price, instead of alch value",
position = 35
)
default boolean sortByGEPrice()
{
return false;
}
@ConfigItem(
keyName = "rightClickHidden",
name = "Right click hidden items",
description = "Places hidden items below the 'Walk here' option, making it so that you need to right click to pick them up",
position = 36
)
default boolean rightClickHidden()
{
return false;
}
} }

View File

@@ -38,6 +38,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.List;
import java.util.Comparator;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Perspective; import net.runelite.api.Perspective;
@@ -177,7 +179,13 @@ public class GroundItemsOverlay extends Overlay
final boolean onlyShowLoot = config.onlyShowLoot(); final boolean onlyShowLoot = config.onlyShowLoot();
for (GroundItem item : groundItemList) List<GroundItem> groundItemListAsList = new ArrayList<>(groundItemList); // make a copy so we can non-destructively modify the list
Comparator<GroundItem> compareByHaPrice = Comparator.comparingInt(GroundItem::getHaPrice);
Comparator<GroundItem> compareByGePrice = Comparator.comparingInt(GroundItem::getGePrice);
groundItemListAsList.sort(config.sortByGEPrice() ? compareByGePrice : compareByHaPrice);
for (GroundItem item : groundItemListAsList)
{ {
final LocalPoint groundPoint = LocalPoint.fromWorld(client, item.getLocation()); final LocalPoint groundPoint = LocalPoint.fromWorld(client, item.getLocation());

View File

@@ -42,6 +42,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@@ -116,6 +118,7 @@ public class GroundItemsPlugin extends Plugin
private static final int FOURTH_OPTION = MenuAction.GROUND_ITEM_FOURTH_OPTION.getId(); private static final int FOURTH_OPTION = MenuAction.GROUND_ITEM_FOURTH_OPTION.getId();
private static final int FIFTH_OPTION = MenuAction.GROUND_ITEM_FIFTH_OPTION.getId(); private static final int FIFTH_OPTION = MenuAction.GROUND_ITEM_FIFTH_OPTION.getId();
private static final int EXAMINE_ITEM = MenuAction.EXAMINE_ITEM_GROUND.getId(); private static final int EXAMINE_ITEM = MenuAction.EXAMINE_ITEM_GROUND.getId();
private static final int WALK = MenuAction.WALK.getId();
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE) @Setter(AccessLevel.PACKAGE)
@@ -356,11 +359,6 @@ public class GroundItemsPlugin extends Plugin
@Subscribe @Subscribe
public void onClientTick(ClientTick event) public void onClientTick(ClientTick event)
{ {
if (!config.collapseEntries())
{
return;
}
final MenuEntry[] menuEntries = client.getMenuEntries(); final MenuEntry[] menuEntries = client.getMenuEntries();
final List<MenuEntryWithCount> newEntries = new ArrayList<>(menuEntries.length); final List<MenuEntryWithCount> newEntries = new ArrayList<>(menuEntries.length);
@@ -369,16 +367,19 @@ public class GroundItemsPlugin extends Plugin
{ {
MenuEntry menuEntry = menuEntries[i]; MenuEntry menuEntry = menuEntries[i];
int menuType = menuEntry.getType(); if (config.collapseEntries())
if (menuType == FIRST_OPTION || menuType == SECOND_OPTION || menuType == THIRD_OPTION
|| menuType == FOURTH_OPTION || menuType == FIFTH_OPTION || menuType == EXAMINE_ITEM)
{ {
for (MenuEntryWithCount entryWCount : newEntries) int menuType = menuEntry.getType();
if (menuType == FIRST_OPTION || menuType == SECOND_OPTION || menuType == THIRD_OPTION
|| menuType == FOURTH_OPTION || menuType == FIFTH_OPTION || menuType == EXAMINE_ITEM)
{ {
if (entryWCount.getEntry().equals(menuEntry)) for (MenuEntryWithCount entryWCount : newEntries)
{ {
entryWCount.increment(); if (entryWCount.getEntry().equals(menuEntry))
continue outer; {
entryWCount.increment();
continue outer;
}
} }
} }
} }
@@ -388,13 +389,64 @@ public class GroundItemsPlugin extends Plugin
Collections.reverse(newEntries); Collections.reverse(newEntries);
newEntries.sort((a, b) ->
{
final int aMenuType = a.getEntry().getType();
if (aMenuType == FIRST_OPTION || aMenuType == SECOND_OPTION || aMenuType == THIRD_OPTION
|| aMenuType == FOURTH_OPTION || aMenuType == FIFTH_OPTION || aMenuType == EXAMINE_ITEM
|| aMenuType == WALK)
{ // only check for item related menu types, so we don't sort other stuff
final int bMenuType = b.getEntry().getType();
if (bMenuType == FIRST_OPTION || bMenuType == SECOND_OPTION || bMenuType == THIRD_OPTION
|| bMenuType == FOURTH_OPTION || bMenuType == FIFTH_OPTION || bMenuType == EXAMINE_ITEM
|| bMenuType == WALK)
{
final MenuEntry aEntry = a.getEntry();
final int aId = aEntry.getIdentifier();
final boolean aHidden = isItemIdHidden(aId);
final int aQuantity = getCollapsedItemQuantity(aId, aEntry.getTarget());
final MenuEntry bEntry = b.getEntry();
final int bId = bEntry.getIdentifier();
final boolean bHidden = isItemIdHidden(bId);
final int bQuantity = getCollapsedItemQuantity(bId, bEntry.getTarget());
// only put items below walk if the config is set for it
if (config.rightClickHidden())
{
if (aHidden && bMenuType == WALK)
return -1;
if (bHidden && aMenuType == WALK)
return 1;
}
// sort hidden items below non-hidden items
if (aHidden && !bHidden && bMenuType != WALK)
return -1;
if (bHidden && !aHidden && aMenuType != WALK)
return 1;
// RS sorts by alch price by default, so no need to sort if config not set
if (config.sortByGEPrice())
return (getGePriceFromItemId(aId) * aQuantity) - (getGePriceFromItemId(bId) * bQuantity);
}
}
return 0;
});
client.setMenuEntries(newEntries.stream().map(e -> client.setMenuEntries(newEntries.stream().map(e ->
{ {
final MenuEntry entry = e.getEntry(); final MenuEntry entry = e.getEntry();
final int count = e.getCount();
if (count > 1) if (config.collapseEntries())
{ {
entry.setTarget(entry.getTarget() + " x " + count); final int count = e.getCount();
if (count > 1)
{
entry.setTarget(entry.getTarget() + " x " + count);
}
} }
return entry; return entry;
@@ -699,8 +751,46 @@ public class GroundItemsPlugin extends Plugin
// Explicit highlight takes priority over implicit hide // Explicit highlight takes priority over implicit hide
return isExplicitHidden || (!isExplicitHighlight && canBeHidden && underGe && underHa) return isExplicitHidden || (!isExplicitHighlight && canBeHidden && underGe && underHa)
? config.hiddenColor() ? config.hiddenColor()
: null; : null;
}
private int getGePriceFromItemId(int itemId)
{
final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId;
return itemManager.getItemPrice(realItemId);
}
private boolean isItemIdHidden(int itemId)
{
final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemId;
final int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT);
final int gePrice = itemManager.getItemPrice(realItemId);
return getHidden(itemComposition.getName(), gePrice, alchPrice, itemComposition.isTradeable()) != null;
}
private int getCollapsedItemQuantity(int itemId, String item)
{
final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
final boolean itemNameIncludesQuantity = Pattern.compile("\\(\\d+\\)").matcher(itemComposition.getName()).find();
Matcher matcher = Pattern.compile("\\((\\d+)\\)").matcher(item);
int matches = 0;
String lastMatch = "1";
while (matcher.find())
{
// so that "Prayer Potion (4)" returns 1 instead of 4 and "Coins (25)" returns 25 instead of 1
if (!itemNameIncludesQuantity || matches >= 1)
lastMatch = matcher.group(1);
matches++;
}
return Integer.parseInt(lastMatch);
} }
Color getItemColor(Color highlighted, Color hidden) Color getItemColor(Color highlighted, Color hidden)