bank plugin: add item value searching
Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
@@ -26,15 +26,24 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.bank;
|
package net.runelite.client.plugins.bank;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.collect.HashMultiset;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
|
import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER;
|
||||||
import net.runelite.api.InventoryID;
|
import net.runelite.api.InventoryID;
|
||||||
import net.runelite.api.Item;
|
import net.runelite.api.Item;
|
||||||
|
import net.runelite.api.ItemComposition;
|
||||||
import net.runelite.api.ItemContainer;
|
import net.runelite.api.ItemContainer;
|
||||||
|
import net.runelite.api.ItemID;
|
||||||
import net.runelite.api.MenuEntry;
|
import net.runelite.api.MenuEntry;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
import net.runelite.api.events.ItemContainerChanged;
|
import net.runelite.api.events.ItemContainerChanged;
|
||||||
@@ -48,6 +57,7 @@ import net.runelite.api.widgets.WidgetInfo;
|
|||||||
import net.runelite.client.callback.ClientThread;
|
import net.runelite.client.callback.ClientThread;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
import net.runelite.client.plugins.banktags.tabs.BankSearch;
|
import net.runelite.client.plugins.banktags.tabs.BankSearch;
|
||||||
@@ -77,12 +87,20 @@ public class BankPlugin extends Plugin
|
|||||||
private static final String DEPOSIT_LOOT = "Deposit loot";
|
private static final String DEPOSIT_LOOT = "Deposit loot";
|
||||||
private static final String SEED_VAULT_TITLE = "Seed Vault";
|
private static final String SEED_VAULT_TITLE = "Seed Vault";
|
||||||
|
|
||||||
|
private static final String NUMBER_REGEX = "[0-9]+(\\.[0-9]+)?[kmb]?";
|
||||||
|
private static final Pattern VALUE_SEARCH_PATTERN = Pattern.compile("^(?<mode>ge|ha|alch)?" +
|
||||||
|
" *(((?<op>[<>=]|>=|<=) *(?<num>" + NUMBER_REGEX + "))|" +
|
||||||
|
"((?<num1>" + NUMBER_REGEX + ") *- *(?<num2>" + NUMBER_REGEX + ")))$", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ClientThread clientThread;
|
private ClientThread clientThread;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ItemManager itemManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BankConfig config;
|
private BankConfig config;
|
||||||
|
|
||||||
@@ -96,6 +114,7 @@ public class BankPlugin extends Plugin
|
|||||||
private ContainerCalculation seedVaultCalculation;
|
private ContainerCalculation seedVaultCalculation;
|
||||||
|
|
||||||
private boolean forceRightClickFlag;
|
private boolean forceRightClickFlag;
|
||||||
|
private Multiset<Integer> itemQuantities; // bank item quantities for bank value search
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
BankConfig getConfig(ConfigManager configManager)
|
BankConfig getConfig(ConfigManager configManager)
|
||||||
@@ -108,6 +127,7 @@ public class BankPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
clientThread.invokeLater(() -> bankSearch.reset(false));
|
clientThread.invokeLater(() -> bankSearch.reset(false));
|
||||||
forceRightClickFlag = false;
|
forceRightClickFlag = false;
|
||||||
|
itemQuantities = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -146,23 +166,36 @@ public class BankPlugin extends Plugin
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||||
{
|
{
|
||||||
if (!event.getEventName().equals("setBankTitle"))
|
int[] intStack = client.getIntStack();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ContainerPrices prices = bankCalculation.calculate(getBankTabItems());
|
|
||||||
if (prices == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String strCurrentTab = createValueText(prices);
|
|
||||||
|
|
||||||
String[] stringStack = client.getStringStack();
|
String[] stringStack = client.getStringStack();
|
||||||
|
int intStackSize = client.getIntStackSize();
|
||||||
int stringStackSize = client.getStringStackSize();
|
int stringStackSize = client.getStringStackSize();
|
||||||
|
|
||||||
stringStack[stringStackSize - 1] += strCurrentTab;
|
switch (event.getEventName())
|
||||||
|
{
|
||||||
|
case "setBankTitle":
|
||||||
|
final ContainerPrices prices = bankCalculation.calculate(getBankTabItems());
|
||||||
|
if (prices == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String strCurrentTab = createValueText(prices);
|
||||||
|
|
||||||
|
stringStack[stringStackSize - 1] += strCurrentTab;
|
||||||
|
break;
|
||||||
|
case "bankSearchFilter":
|
||||||
|
int itemId = intStack[intStackSize - 1];
|
||||||
|
String search = stringStack[stringStackSize - 1];
|
||||||
|
|
||||||
|
if (valueSearch(itemId, search))
|
||||||
|
{
|
||||||
|
// return true
|
||||||
|
intStack[intStackSize - 2] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -179,12 +212,16 @@ public class BankPlugin extends Plugin
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onItemContainerChanged(ItemContainerChanged event)
|
public void onItemContainerChanged(ItemContainerChanged event)
|
||||||
{
|
{
|
||||||
if (event.getContainerId() != InventoryID.SEED_VAULT.getId() || !config.seedVaultValue())
|
int containerId = event.getContainerId();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSeedVaultTotal();
|
if (containerId == InventoryID.BANK.getId())
|
||||||
|
{
|
||||||
|
itemQuantities = null;
|
||||||
|
}
|
||||||
|
else if (containerId == InventoryID.SEED_VAULT.getId() && config.seedVaultValue())
|
||||||
|
{
|
||||||
|
updateSeedVaultTotal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createValueText(final ContainerPrices prices)
|
private String createValueText(final ContainerPrices prices)
|
||||||
@@ -297,4 +334,100 @@ public class BankPlugin extends Plugin
|
|||||||
|
|
||||||
return itemContainer.getItems();
|
return itemContainer.getItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean valueSearch(final int itemId, final String str)
|
||||||
|
{
|
||||||
|
final Matcher matcher = VALUE_SEARCH_PATTERN.matcher(str);
|
||||||
|
if (!matcher.matches())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count bank items and remember it for determining item quantity
|
||||||
|
if (itemQuantities == null)
|
||||||
|
{
|
||||||
|
itemQuantities = getBankItemSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
|
||||||
|
long gePrice = (long) itemManager.getItemPrice(itemId) * (long) itemQuantities.count(itemId);
|
||||||
|
long haPrice = (long) (itemComposition.getPrice() * HIGH_ALCHEMY_MULTIPLIER) * (long) itemQuantities.count(itemId);
|
||||||
|
|
||||||
|
long value = Math.max(gePrice, haPrice);
|
||||||
|
|
||||||
|
final String mode = matcher.group("mode");
|
||||||
|
if (mode != null)
|
||||||
|
{
|
||||||
|
value = mode.toLowerCase().equals("ge") ? gePrice : haPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String op = matcher.group("op");
|
||||||
|
if (op != null)
|
||||||
|
{
|
||||||
|
long compare;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
compare = StackFormatter.stackSizeToQuantity(matcher.group("num"));
|
||||||
|
}
|
||||||
|
catch (ParseException e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case ">":
|
||||||
|
return value > compare;
|
||||||
|
case "<":
|
||||||
|
return value < compare;
|
||||||
|
case "=":
|
||||||
|
return value == compare;
|
||||||
|
case ">=":
|
||||||
|
return value >= compare;
|
||||||
|
case "<=":
|
||||||
|
return value <= compare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String num1 = matcher.group("num1");
|
||||||
|
final String num2 = matcher.group("num2");
|
||||||
|
if (num1 != null && num2 != null)
|
||||||
|
{
|
||||||
|
long compare1, compare2;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
compare1 = StackFormatter.stackSizeToQuantity(num1);
|
||||||
|
compare2 = StackFormatter.stackSizeToQuantity(num2);
|
||||||
|
}
|
||||||
|
catch (ParseException e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return compare1 <= value && compare2 >= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Multiset<Integer> getBankItemSet()
|
||||||
|
{
|
||||||
|
ItemContainer itemContainer = client.getItemContainer(InventoryID.BANK);
|
||||||
|
if (itemContainer == null)
|
||||||
|
{
|
||||||
|
return HashMultiset.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Multiset<Integer> set = HashMultiset.create();
|
||||||
|
for (Item item : itemContainer.getItems())
|
||||||
|
{
|
||||||
|
if (item.getId() != ItemID.BANK_FILLER)
|
||||||
|
{
|
||||||
|
set.add(item.getId(), item.getQuantity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Ron Young <https://github.com/raiyni>
|
||||||
|
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.runelite.client.plugins.bank;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.testing.fieldbinder.Bind;
|
||||||
|
import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.InventoryID;
|
||||||
|
import net.runelite.api.Item;
|
||||||
|
import net.runelite.api.ItemComposition;
|
||||||
|
import net.runelite.api.ItemContainer;
|
||||||
|
import net.runelite.api.ItemID;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class BankPluginTest
|
||||||
|
{
|
||||||
|
@Mock
|
||||||
|
@Bind
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
@Bind
|
||||||
|
private ItemManager itemManager;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
@Bind
|
||||||
|
private BankConfig bankConfig;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BankPlugin bankPlugin;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before()
|
||||||
|
{
|
||||||
|
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValueSearch()
|
||||||
|
{
|
||||||
|
int itemId = ItemID.ABYSSAL_WHIP;
|
||||||
|
|
||||||
|
ItemContainer itemContainer = mock(ItemContainer.class);
|
||||||
|
when(itemContainer.getItems()).thenReturn(new Item[]{new Item(itemId, 30)});
|
||||||
|
when(client.getItemContainer(InventoryID.BANK)).thenReturn(itemContainer);
|
||||||
|
|
||||||
|
ItemComposition comp = mock(ItemComposition.class);
|
||||||
|
when(comp.getId())
|
||||||
|
.thenReturn(itemId);
|
||||||
|
|
||||||
|
// 60k HA price * 30 = 1.8m
|
||||||
|
when(comp.getPrice())
|
||||||
|
.thenReturn(100_000);
|
||||||
|
|
||||||
|
// 400k GE Price * 30 = 12m
|
||||||
|
when(itemManager.getItemPrice(itemId))
|
||||||
|
.thenReturn(400_000);
|
||||||
|
when(itemManager.getItemComposition(itemId))
|
||||||
|
.thenReturn(comp);
|
||||||
|
|
||||||
|
assertTrue(bankPlugin.valueSearch(itemId, ">500k"));
|
||||||
|
assertTrue(bankPlugin.valueSearch(itemId, "< 5.5b"));
|
||||||
|
assertTrue(bankPlugin.valueSearch(itemId, "500k - 20.6m"));
|
||||||
|
|
||||||
|
assertTrue(bankPlugin.valueSearch(itemId, "ha=1.8m"));
|
||||||
|
assertTrue(bankPlugin.valueSearch(itemId, "ha 500k - 20.6m"));
|
||||||
|
assertTrue(bankPlugin.valueSearch(itemId, "ha > 940k"));
|
||||||
|
|
||||||
|
assertFalse(bankPlugin.valueSearch(itemId, "<500k"));
|
||||||
|
assertFalse(bankPlugin.valueSearch(itemId, "ha >2m"));
|
||||||
|
assertFalse(bankPlugin.valueSearch(itemId, "ge > 0.02b"));
|
||||||
|
|
||||||
|
assertFalse(bankPlugin.valueSearch(itemId, "1000k"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user