This commit is contained in:
therealunull
2020-12-14 09:12:44 -05:00
parent a55f9502e2
commit 695e331d22
9 changed files with 839 additions and 6 deletions

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2018, TheLonelyDev <https://github.com/TheLonelyDev>
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
* 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 java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Keybind;
@ConfigGroup("bank")
public interface BankConfig extends Config
{
@ConfigItem(
keyName = "showGE",
name = "Show Grand Exchange price",
description = "Show grand exchange price total (GE)",
position = 1
)
default boolean showGE()
{
return true;
}
@ConfigItem(
keyName = "showHA",
name = "Show high alchemy price",
description = "Show high alchemy price total (HA)",
position = 2
)
default boolean showHA()
{
return false;
}
@ConfigItem(
keyName = "showExact",
name = "Show exact bank value",
description = "Show exact bank value",
position = 3
)
default boolean showExact()
{
return false;
}
@ConfigItem(
keyName = "rightClickBankInventory",
name = "Disable left click bank inventory",
description = "Configures whether the bank inventory button will bank your inventory on left click",
position = 4
)
default boolean rightClickBankInventory()
{
return false;
}
@ConfigItem(
keyName = "rightClickBankEquip",
name = "Disable left click bank equipment",
description = "Configures whether the bank equipment button will bank your equipment on left click",
position = 5
)
default boolean rightClickBankEquip()
{
return false;
}
@ConfigItem(
keyName = "rightClickBankLoot",
name = "Disable left click bank looting bag",
description = "Configures whether the bank looting bag button will bank your looting bag contents on left click",
position = 6
)
default boolean rightClickBankLoot()
{
return false;
}
@ConfigItem(
keyName = "seedVaultValue",
name = "Show seed vault value",
description = "Adds the total value of all seeds inside the seed vault to the title",
position = 7
)
default boolean seedVaultValue()
{
return true;
}
@ConfigItem(
keyName = "bankPinKeyboard",
name = "Keyboard Bankpin",
description = "Allows using the keyboard keys for bank pin input",
position = 8
)
default boolean bankPinKeyboard()
{
return false;
}
@ConfigItem(
keyName = "searchKeybind",
name = "Search Shortcut",
description = "Keyboard shortcut for initiating a bank search",
position = 9
)
default Keybind searchKeybind()
{
return new Keybind(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK);
}
}

View File

@@ -0,0 +1,545 @@
/*
* Copyright (c) 2018, TheLonelyDev <https://github.com/TheLonelyDev>
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* 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.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.inject.Provides;
import java.awt.event.KeyEvent;
import java.text.ParseException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
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.api.MenuEntry;
import net.runelite.api.ScriptID;
import net.runelite.api.VarClientStr;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuShouldLeftClick;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.ScriptPostFired;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.JavaScriptCallback;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.Keybind;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.QuantityFormatter;
@PluginDescriptor(
name = "Bank",
description = "Modifications to the banking interface",
tags = {"grand", "exchange", "high", "alchemy", "prices", "deposit"}
)
@Slf4j
public class BankPlugin extends Plugin
{
private static final String DEPOSIT_WORN = "Deposit worn items";
private static final String DEPOSIT_INVENTORY = "Deposit inventory";
private static final String DEPOSIT_LOOT = "Deposit loot";
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
private Client client;
@Inject
private ClientThread clientThread;
@Inject
private ItemManager itemManager;
@Inject
private BankConfig config;
@Inject
private BankSearch bankSearch;
@Inject
private KeyManager keyManager;
private boolean forceRightClickFlag;
private Multiset<Integer> itemQuantities; // bank item quantities for bank value search
private String searchString;
private final KeyListener searchHotkeyListener = new KeyListener()
{
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
Keybind keybind = config.searchKeybind();
if (keybind.matches(e))
{
Widget bankContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
if (bankContainer == null || bankContainer.isSelfHidden())
{
return;
}
log.debug("Search hotkey pressed");
bankSearch.initSearch();
e.consume();
}
}
@Override
public void keyReleased(KeyEvent e)
{
}
};
@Provides
BankConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(BankConfig.class);
}
@Override
protected void startUp()
{
keyManager.registerKeyListener(searchHotkeyListener);
}
@Override
protected void shutDown()
{
keyManager.unregisterKeyListener(searchHotkeyListener);
clientThread.invokeLater(() -> bankSearch.reset(false));
forceRightClickFlag = false;
itemQuantities = null;
searchString = null;
}
@Subscribe
public void onMenuShouldLeftClick(MenuShouldLeftClick event)
{
if (!forceRightClickFlag)
{
return;
}
forceRightClickFlag = false;
MenuEntry[] menuEntries = client.getMenuEntries();
for (MenuEntry entry : menuEntries)
{
if ((entry.getOption().equals(DEPOSIT_WORN) && config.rightClickBankEquip())
|| (entry.getOption().equals(DEPOSIT_INVENTORY) && config.rightClickBankInventory())
|| (entry.getOption().equals(DEPOSIT_LOOT) && config.rightClickBankLoot()))
{
event.setForceRightClick(true);
return;
}
}
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event)
{
if ((event.getOption().equals(DEPOSIT_WORN) && config.rightClickBankEquip())
|| (event.getOption().equals(DEPOSIT_INVENTORY) && config.rightClickBankInventory())
|| (event.getOption().equals(DEPOSIT_LOOT) && config.rightClickBankLoot()))
{
forceRightClickFlag = true;
}
}
@Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent event)
{
int[] intStack = client.getIntStack();
String[] stringStack = client.getStringStack();
int intStackSize = client.getIntStackSize();
int stringStackSize = client.getStringStackSize();
switch (event.getEventName())
{
case "bankSearchFilter":
int itemId = intStack[intStackSize - 1];
String search = stringStack[stringStackSize - 1];
if (valueSearch(itemId, search))
{
// return true
intStack[intStackSize - 2] = 1;
}
break;
case "bankpinButtonSetup":
{
if (!config.bankPinKeyboard())
{
return;
}
final int compId = intStack[intStackSize - 2];
final int buttonId = intStack[intStackSize - 1];
Widget button = client.getWidget(compId);
Widget buttonRect = button.getChild(0);
final Object[] onOpListener = buttonRect.getOnOpListener();
buttonRect.setOnKeyListener((JavaScriptCallback) e ->
{
int typedChar = e.getTypedKeyChar() - '0';
if (typedChar != buttonId)
{
return;
}
log.debug("Bank pin keypress");
final String input = client.getVar(VarClientStr.CHATBOX_TYPED_TEXT);
clientThread.invokeLater(() ->
{
// reset chatbox input to avoid pin going to chatbox..
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, input);
client.runScript(ScriptID.CHAT_PROMPT_INIT);
client.runScript(onOpListener);
});
});
break;
}
}
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
if (event.getGroupId() != WidgetID.SEED_VAULT_GROUP_ID || !config.seedVaultValue())
{
return;
}
updateSeedVaultTotal();
}
@Subscribe
public void onScriptPostFired(ScriptPostFired event)
{
if (event.getScriptId() == ScriptID.BANKMAIN_BUILD)
{
// Compute bank prices using only the shown items so that we can show bank value during searches
final Widget bankItemContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
final ItemContainer bankContainer = client.getItemContainer(InventoryID.BANK);
final Widget[] children = bankItemContainer.getChildren();
long geTotal = 0, haTotal = 0;
if (children != null)
{
log.debug("Computing bank price of {} items", bankContainer.size());
// The first components are the bank items, followed by tabs etc. There are always 816 components regardless
// of bank size, but we only need to check up to the bank size.
for (int i = 0; i < bankContainer.size(); ++i)
{
Widget child = children[i];
if (child != null && !child.isSelfHidden() && child.getItemId() > -1)
{
final int alchPrice = getHaPrice(child.getItemId());
geTotal += (long) itemManager.getItemPrice(child.getItemId()) * child.getItemQuantity();
haTotal += (long) alchPrice * child.getItemQuantity();
}
}
Widget bankTitle = client.getWidget(WidgetInfo.BANK_TITLE_BAR);
bankTitle.setText(bankTitle.getText() + createValueText(geTotal, haTotal));
}
}
else if (event.getScriptId() == ScriptID.BANKMAIN_SEARCH_REFRESH)
{
// vanilla only lays out the bank every 40 client ticks, so if the search input has changed,
// and the bank wasn't laid out this tick, lay it out early
final String inputText = client.getVar(VarClientStr.INPUT_TEXT);
if (searchString != inputText && client.getGameCycle() % 40 != 0)
{
clientThread.invokeLater(bankSearch::layoutBank);
searchString = inputText;
}
}
}
@Subscribe
public void onItemContainerChanged(ItemContainerChanged event)
{
int containerId = event.getContainerId();
if (containerId == InventoryID.BANK.getId())
{
itemQuantities = null;
}
else if (containerId == InventoryID.SEED_VAULT.getId() && config.seedVaultValue())
{
updateSeedVaultTotal();
}
}
private String createValueText(long gePrice, long haPrice)
{
StringBuilder stringBuilder = new StringBuilder();
if (config.showGE() && gePrice != 0)
{
stringBuilder.append(" (");
if (config.showHA())
{
stringBuilder.append("GE: ");
}
if (config.showExact())
{
stringBuilder.append(QuantityFormatter.formatNumber(gePrice));
}
else
{
stringBuilder.append(QuantityFormatter.quantityToStackSize(gePrice));
}
stringBuilder.append(')');
}
if (config.showHA() && haPrice != 0)
{
stringBuilder.append(" (");
if (config.showGE())
{
stringBuilder.append("HA: ");
}
if (config.showExact())
{
stringBuilder.append(QuantityFormatter.formatNumber(haPrice));
}
else
{
stringBuilder.append(QuantityFormatter.quantityToStackSize(haPrice));
}
stringBuilder.append(')');
}
return stringBuilder.toString();
}
private void updateSeedVaultTotal()
{
final Widget titleContainer = client.getWidget(WidgetInfo.SEED_VAULT_TITLE_CONTAINER);
if (titleContainer == null)
{
return;
}
final Widget title = titleContainer.getChild(1);
if (title == null)
{
return;
}
final ContainerPrices prices = calculate(getSeedVaultItems());
if (prices == null)
{
return;
}
final String titleText = createValueText(prices.getGePrice(), prices.getHighAlchPrice());
title.setText(SEED_VAULT_TITLE + titleText);
}
private Item[] getSeedVaultItems()
{
final ItemContainer itemContainer = client.getItemContainer(InventoryID.SEED_VAULT);
if (itemContainer == null)
{
return null;
}
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);
final int qty = itemQuantities.count(itemId);
final long gePrice = (long) itemManager.getItemPrice(itemId) * qty;
final long haPrice = (long) itemComposition.getHaPrice() * qty;
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 = QuantityFormatter.parseQuantity(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 = QuantityFormatter.parseQuantity(num1);
compare2 = QuantityFormatter.parseQuantity(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;
}
@Nullable
ContainerPrices calculate(@Nullable Item[] items)
{
if (items == null)
{
return null;
}
long ge = 0;
long alch = 0;
for (final Item item : items)
{
final int qty = item.getQuantity();
final int id = item.getId();
if (id <= 0 || qty == 0)
{
continue;
}
alch += (long) getHaPrice(id) * qty;
ge += (long) itemManager.getItemPrice(id) * qty;
}
return new ContainerPrices(ge, alch);
}
private int getHaPrice(int itemId)
{
switch (itemId)
{
case ItemID.COINS_995:
return 1;
case ItemID.PLATINUM_TOKEN:
return 1000;
default:
return itemManager.getItemComposition(itemId).getHaPrice();
}
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
* 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 javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.ScriptID;
import net.runelite.api.VarClientInt;
import net.runelite.api.VarClientStr;
import net.runelite.api.vars.InputType;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.callback.ClientThread;
import org.apache.commons.lang3.ArrayUtils;
@Singleton
public class BankSearch
{
private final Client client;
private final ClientThread clientThread;
@Inject
private BankSearch(
final Client client,
final ClientThread clientThread
)
{
this.client = client;
this.clientThread = clientThread;
}
public void layoutBank()
{
Widget bankContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
if (bankContainer == null || bankContainer.isHidden())
{
return;
}
Object[] scriptArgs = bankContainer.getOnInvTransmitListener();
if (scriptArgs == null)
{
return;
}
client.runScript(scriptArgs);
}
public void initSearch()
{
clientThread.invoke(() ->
{
Widget bankContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
if (bankContainer == null || bankContainer.isHidden())
{
return;
}
Object[] bankBuildArgs = bankContainer.getOnInvTransmitListener();
if (bankBuildArgs == null)
{
return;
}
// the search toggle script requires 1 as its first argument
Object[] searchToggleArgs = ArrayUtils.insert(1, bankBuildArgs, 1);
searchToggleArgs[0] = ScriptID.BANKMAIN_SEARCH_TOGGLE;
// reset search to clear tab tags and also allow us to initiate a new search while searching
reset(true);
client.runScript(searchToggleArgs);
});
}
public void reset(boolean closeChat)
{
clientThread.invoke(() ->
{
// This ensures that any chatbox input (e.g from search) will not remain visible when
// selecting/changing tab
if (closeChat)
{
// this clears the input text and type, and resets the chatbox to allow input
client.runScript(ScriptID.MESSAGE_LAYER_CLOSE, 1, 1);
}
else
{
client.setVar(VarClientInt.INPUT_TYPE, InputType.NONE.getType());
client.setVar(VarClientStr.INPUT_TEXT, "");
}
layoutBank();
});
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
* 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 lombok.Value;
@Value
class ContainerPrices
{
private long gePrice;
private long highAlchPrice;
}

View File

@@ -27,7 +27,6 @@ package net.runelite.client.plugins.blastmine;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import java.awt.Color;
@ConfigGroup("blastmine")

View File

@@ -27,7 +27,6 @@ package net.runelite.client.plugins.devtools;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.CollisionDataFlag;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

View File

@@ -28,7 +28,11 @@ import java.util.ArrayList;
import java.util.List;
import net.runelite.api.Client;
import net.runelite.api.Varbits;
import net.runelite.client.plugins.itemstats.*;
import net.runelite.client.plugins.itemstats.Effect;
import net.runelite.client.plugins.itemstats.Positivity;
import net.runelite.client.plugins.itemstats.RangeStatChange;
import net.runelite.client.plugins.itemstats.StatChange;
import net.runelite.client.plugins.itemstats.StatsChanges;
import net.runelite.client.plugins.itemstats.stats.Stat;
import net.runelite.client.plugins.itemstats.stats.Stats;

View File

@@ -36,7 +36,6 @@ import javax.inject.Singleton;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.coords.WorldPoint;
import static net.runelite.client.plugins.kourendlibrary.Book.*;
/**

View File

@@ -26,9 +26,7 @@ package net.runelite.client.plugins.xptracker;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.function.Function;
import static net.runelite.client.plugins.xptracker.XpInfoBox.TWO_DECIMAL_FORMAT;
@Getter