banktags, cooking, xpdrop, fishing, friendnotes
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.banktags;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("banktags")
|
||||
public interface BankTagsConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "useTabs",
|
||||
name = "Use Tag Tabs",
|
||||
description = "Enable the ability to add tabs to your bank which allow fast access to tags.",
|
||||
position = 1
|
||||
)
|
||||
default boolean tabs()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "rememberTab",
|
||||
name = "Remember last Tag Tab",
|
||||
description = "Enable the ability to remember last Tag Tab when closing/opening the bank.",
|
||||
position = 2
|
||||
)
|
||||
default boolean rememberTab()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "removeTabSeparators",
|
||||
name = "Remove tab separators",
|
||||
description = "Remove the tab separators normally present in tag tabs",
|
||||
position = 3
|
||||
)
|
||||
default boolean removeSeparators()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "preventTagTabDrags",
|
||||
name = "Prevent tag tab item dragging",
|
||||
description = "Ignore dragged items to prevent unwanted bank item reordering",
|
||||
position = 4
|
||||
)
|
||||
default boolean preventTagTabDrags()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "position",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int position()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "position",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void position(int idx);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "tab",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default String tab()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "tab",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void tab(String tab);
|
||||
}
|
||||
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.banktags;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.primitives.Shorts;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
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.KeyCode;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.events.DraggingWidgetChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.GrandExchangeSearched;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.ScriptPostFired;
|
||||
import net.runelite.api.events.ScriptPreFired;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
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.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.ItemVariationMapping;
|
||||
import net.runelite.client.game.SpriteManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.input.MouseWheelListener;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.banktags.tabs.TabInterface;
|
||||
import static net.runelite.client.plugins.banktags.tabs.TabInterface.FILTERED_CHARS;
|
||||
import net.runelite.client.plugins.banktags.tabs.TabSprites;
|
||||
import net.runelite.client.plugins.banktags.tabs.TagTab;
|
||||
import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Bank Tags",
|
||||
description = "Enable tagging of bank items and searching of bank tags",
|
||||
tags = {"searching", "tagging"}
|
||||
)
|
||||
@PluginDependency(ClueScrollPlugin.class)
|
||||
public class BankTagsPlugin extends Plugin implements MouseWheelListener
|
||||
{
|
||||
public static final String CONFIG_GROUP = "banktags";
|
||||
public static final String TAG_SEARCH = "tag:";
|
||||
private static final String EDIT_TAGS_MENU_OPTION = "Edit-tags";
|
||||
public static final String ICON_SEARCH = "icon_";
|
||||
public static final String TAG_TABS_CONFIG = "tagtabs";
|
||||
public static final String VAR_TAG_SUFFIX = "*";
|
||||
private static final int ITEMS_PER_ROW = 8;
|
||||
private static final int ITEM_VERTICAL_SPACING = 36;
|
||||
private static final int ITEM_HORIZONTAL_SPACING = 48;
|
||||
private static final int ITEM_ROW_START = 51;
|
||||
|
||||
private static final int MAX_RESULT_COUNT = 250;
|
||||
|
||||
private static final String SEARCH_BANK_INPUT_TEXT =
|
||||
"Show items whose names or tags contain the following text:<br>" +
|
||||
"(To show only tagged items, start your search with 'tag:')";
|
||||
private static final String SEARCH_BANK_INPUT_TEXT_FOUND =
|
||||
"Show items whose names or tags contain the following text: (%d found)<br>" +
|
||||
"(To show only tagged items, start your search with 'tag:')";
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private MouseManager mouseManager;
|
||||
|
||||
@Inject
|
||||
private BankTagsConfig config;
|
||||
|
||||
@Inject
|
||||
private TagManager tagManager;
|
||||
|
||||
@Inject
|
||||
private TabInterface tabInterface;
|
||||
|
||||
@Inject
|
||||
private SpriteManager spriteManager;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Provides
|
||||
BankTagsConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(BankTagsConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConfiguration()
|
||||
{
|
||||
List<String> extraKeys = Lists.newArrayList(
|
||||
CONFIG_GROUP + "." + TagManager.ITEM_KEY_PREFIX,
|
||||
CONFIG_GROUP + "." + ICON_SEARCH,
|
||||
CONFIG_GROUP + "." + TAG_TABS_CONFIG
|
||||
);
|
||||
|
||||
for (String prefix : extraKeys)
|
||||
{
|
||||
List<String> keys = configManager.getConfigurationKeys(prefix);
|
||||
for (String key : keys)
|
||||
{
|
||||
String[] str = key.split("\\.", 2);
|
||||
if (str.length == 2)
|
||||
{
|
||||
configManager.unsetConfiguration(str[0], str[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
tabInterface.destroy();
|
||||
tabInterface.init();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
cleanConfig();
|
||||
mouseManager.registerMouseWheelListener(this);
|
||||
clientThread.invokeLater(tabInterface::init);
|
||||
spriteManager.addSpriteOverrides(TabSprites.values());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void cleanConfig()
|
||||
{
|
||||
removeInvalidTags("tagtabs");
|
||||
|
||||
List<String> tags = configManager.getConfigurationKeys(CONFIG_GROUP + ".item_");
|
||||
tags.forEach(s ->
|
||||
{
|
||||
String[] split = s.split("\\.", 2);
|
||||
removeInvalidTags(split[1]);
|
||||
});
|
||||
|
||||
List<String> icons = configManager.getConfigurationKeys(CONFIG_GROUP + ".icon_");
|
||||
icons.forEach(s ->
|
||||
{
|
||||
String[] split = s.split("\\.", 2);
|
||||
String replaced = split[1].replaceAll("[<>/]", "");
|
||||
if (!split[1].equals(replaced))
|
||||
{
|
||||
String value = configManager.getConfiguration(CONFIG_GROUP, split[1]);
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, split[1]);
|
||||
if (replaced.length() > "icon_".length())
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, replaced, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void removeInvalidTags(final String key)
|
||||
{
|
||||
final String value = configManager.getConfiguration(CONFIG_GROUP, key);
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String replaced = value.replaceAll("[<>:/]", "");
|
||||
if (!value.equals(replaced))
|
||||
{
|
||||
replaced = Text.toCSV(Text.fromCSV(replaced));
|
||||
if (replaced.isEmpty())
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, key, replaced);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
mouseManager.unregisterMouseWheelListener(this);
|
||||
clientThread.invokeLater(tabInterface::destroy);
|
||||
spriteManager.removeSpriteOverrides(TabSprites.values());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGrandExchangeSearched(GrandExchangeSearched event)
|
||||
{
|
||||
final String input = client.getVar(VarClientStr.INPUT_TEXT);
|
||||
if (!input.startsWith(TAG_SEARCH))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
event.consume();
|
||||
|
||||
final String tag = input.substring(TAG_SEARCH.length()).trim();
|
||||
final Set<Integer> ids = tagManager.getItemsForTag(tag)
|
||||
.stream()
|
||||
.mapToInt(Math::abs)
|
||||
.mapToObj(ItemVariationMapping::getVariations)
|
||||
.flatMap(Collection::stream)
|
||||
.distinct()
|
||||
.filter(i -> itemManager.getItemComposition(i).isTradeable())
|
||||
.limit(MAX_RESULT_COUNT)
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
|
||||
client.setGeSearchResultIndex(0);
|
||||
client.setGeSearchResultCount(ids.size());
|
||||
client.setGeSearchResultIds(Shorts.toArray(ids));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
{
|
||||
String eventName = event.getEventName();
|
||||
|
||||
int[] intStack = client.getIntStack();
|
||||
String[] stringStack = client.getStringStack();
|
||||
int intStackSize = client.getIntStackSize();
|
||||
int stringStackSize = client.getStringStackSize();
|
||||
|
||||
tabInterface.handleScriptEvent(event);
|
||||
|
||||
switch (eventName)
|
||||
{
|
||||
case "setSearchBankInputText":
|
||||
stringStack[stringStackSize - 1] = SEARCH_BANK_INPUT_TEXT;
|
||||
break;
|
||||
case "setSearchBankInputTextFound":
|
||||
{
|
||||
int matches = intStack[intStackSize - 1];
|
||||
stringStack[stringStackSize - 1] = String.format(SEARCH_BANK_INPUT_TEXT_FOUND, matches);
|
||||
break;
|
||||
}
|
||||
case "bankSearchFilter":
|
||||
final int itemId = intStack[intStackSize - 1];
|
||||
final String searchfilter = stringStack[stringStackSize - 1];
|
||||
|
||||
// This event only fires when the bank is in search mode. It will fire even if there is no search
|
||||
// input. We prevent having a tag tab open while also performing a normal search, so if a tag tab
|
||||
// is active here it must mean we have placed the bank into search mode. See onScriptPostFired().
|
||||
TagTab activeTab = tabInterface.getActiveTab();
|
||||
String search = activeTab != null ? TAG_SEARCH + activeTab.getTag() : searchfilter;
|
||||
|
||||
if (search.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boolean tagSearch = search.startsWith(TAG_SEARCH);
|
||||
if (tagSearch)
|
||||
{
|
||||
search = search.substring(TAG_SEARCH.length()).trim();
|
||||
}
|
||||
|
||||
if (tagManager.findTag(itemId, search))
|
||||
{
|
||||
// return true
|
||||
intStack[intStackSize - 2] = 1;
|
||||
}
|
||||
else if (tagSearch)
|
||||
{
|
||||
// if the item isn't tagged we return false to prevent the item matching if the item name happens
|
||||
// to contain the tag name.
|
||||
intStack[intStackSize - 2] = 0;
|
||||
}
|
||||
break;
|
||||
case "getSearchingTagTab":
|
||||
intStack[intStackSize - 1] = tabInterface.isActive() ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
MenuEntry[] entries = client.getMenuEntries();
|
||||
|
||||
if (event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||
&& event.getOption().equals("Examine"))
|
||||
{
|
||||
Widget container = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
|
||||
Widget item = container.getChild(event.getActionParam0());
|
||||
int itemID = item.getItemId();
|
||||
String text = EDIT_TAGS_MENU_OPTION;
|
||||
int tagCount = tagManager.getTags(itemID, false).size() + tagManager.getTags(itemID, true).size();
|
||||
|
||||
if (tagCount > 0)
|
||||
{
|
||||
text += " (" + tagCount + ")";
|
||||
}
|
||||
|
||||
MenuEntry editTags = new MenuEntry();
|
||||
editTags.setParam0(event.getActionParam0());
|
||||
editTags.setParam1(event.getActionParam1());
|
||||
editTags.setTarget(event.getTarget());
|
||||
editTags.setOption(text);
|
||||
editTags.setType(MenuAction.RUNELITE.getId());
|
||||
editTags.setIdentifier(event.getIdentifier());
|
||||
entries = Arrays.copyOf(entries, entries.length + 1);
|
||||
entries[entries.length - 1] = editTags;
|
||||
client.setMenuEntries(entries);
|
||||
}
|
||||
|
||||
tabInterface.handleAdd(event);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (event.getWidgetId() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||
&& event.getMenuAction() == MenuAction.RUNELITE
|
||||
&& event.getMenuOption().startsWith(EDIT_TAGS_MENU_OPTION))
|
||||
{
|
||||
event.consume();
|
||||
int inventoryIndex = event.getActionParam();
|
||||
ItemContainer bankContainer = client.getItemContainer(InventoryID.BANK);
|
||||
if (bankContainer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Item[] items = bankContainer.getItems();
|
||||
if (inventoryIndex < 0 || inventoryIndex >= items.length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Item item = bankContainer.getItems()[inventoryIndex];
|
||||
if (item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int itemId = item.getId();
|
||||
ItemComposition itemComposition = itemManager.getItemComposition(itemId);
|
||||
String name = itemComposition.getName();
|
||||
|
||||
// Get both tags and vartags and append * to end of vartags name
|
||||
Collection<String> tags = tagManager.getTags(itemId, false);
|
||||
tagManager.getTags(itemId, true).stream()
|
||||
.map(i -> i + "*")
|
||||
.forEach(tags::add);
|
||||
|
||||
String initialValue = Text.toCSV(tags);
|
||||
|
||||
chatboxPanelManager.openTextInput(name + " tags:<br>(append " + VAR_TAG_SUFFIX + " for variation tag)")
|
||||
.addCharValidator(FILTERED_CHARS)
|
||||
.value(initialValue)
|
||||
.onDone((Consumer<String>) (newValue) ->
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
// Split inputted tags to vartags (ending with *) and regular tags
|
||||
final Collection<String> newTags = new ArrayList<>(Text.fromCSV(newValue.toLowerCase()));
|
||||
final Collection<String> newVarTags = new ArrayList<>(newTags).stream().filter(s -> s.endsWith(VAR_TAG_SUFFIX)).map(s ->
|
||||
{
|
||||
newTags.remove(s);
|
||||
return s.substring(0, s.length() - VAR_TAG_SUFFIX.length());
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// And save them
|
||||
tagManager.setTagString(itemId, Text.toCSV(newTags), false);
|
||||
tagManager.setTagString(itemId, Text.toCSV(newVarTags), true);
|
||||
|
||||
// Check both previous and current tags in case the tag got removed in new tags or in case
|
||||
// the tag got added in new tags
|
||||
tabInterface.updateTabIfActive(Text.fromCSV(initialValue.toLowerCase().replaceAll(Pattern.quote(VAR_TAG_SUFFIX), "")));
|
||||
tabInterface.updateTabIfActive(Text.fromCSV(newValue.toLowerCase().replaceAll(Pattern.quote(VAR_TAG_SUFFIX), "")));
|
||||
}))
|
||||
.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
tabInterface.handleClick(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged configChanged)
|
||||
{
|
||||
if (configChanged.getGroup().equals(CONFIG_GROUP) && configChanged.getKey().equals("useTabs"))
|
||||
{
|
||||
if (config.tabs())
|
||||
{
|
||||
clientThread.invokeLater(tabInterface::init);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientThread.invokeLater(tabInterface::destroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptPreFired(ScriptPreFired event)
|
||||
{
|
||||
int scriptId = event.getScriptId();
|
||||
if (scriptId == ScriptID.BANKMAIN_FINISHBUILDING)
|
||||
{
|
||||
// Since we apply tag tab search filters even when the bank is not in search mode,
|
||||
// bankkmain_build will reset the bank title to "The Bank of Gielinor". So apply our
|
||||
// own title.
|
||||
TagTab activeTab = tabInterface.getActiveTab();
|
||||
if (tabInterface.isTagTabActive())
|
||||
{
|
||||
// Tag tab tab has its own title since it isn't a real tag
|
||||
Widget bankTitle = client.getWidget(WidgetInfo.BANK_TITLE_BAR);
|
||||
bankTitle.setText("Tag tab tab");
|
||||
}
|
||||
else if (activeTab != null)
|
||||
{
|
||||
Widget bankTitle = client.getWidget(WidgetInfo.BANK_TITLE_BAR);
|
||||
bankTitle.setText("Tag tab <col=ff0000>" + activeTab.getTag() + "</col>");
|
||||
}
|
||||
}
|
||||
else if (scriptId == ScriptID.BANKMAIN_SEARCH_TOGGLE)
|
||||
{
|
||||
tabInterface.handleSearch();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptPostFired(ScriptPostFired event)
|
||||
{
|
||||
if (event.getScriptId() == ScriptID.BANKMAIN_SEARCHING)
|
||||
{
|
||||
// The return value of bankmain_searching is on the stack. If we have a tag tab active
|
||||
// make it return true to put the bank in a searching state.
|
||||
if (tabInterface.getActiveTab() != null || tabInterface.isTagTabActive())
|
||||
{
|
||||
client.getIntStack()[client.getIntStackSize() - 1] = 1; // true
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getScriptId() != ScriptID.BANKMAIN_BUILD || !config.removeSeparators())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tabInterface.isActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget itemContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
|
||||
if (itemContainer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int items = 0;
|
||||
|
||||
Widget[] containerChildren = itemContainer.getDynamicChildren();
|
||||
|
||||
// sort the child array as the items are not in the displayed order
|
||||
Arrays.sort(containerChildren, Comparator.comparing(Widget::getOriginalY)
|
||||
.thenComparing(Widget::getOriginalX));
|
||||
|
||||
for (Widget child : containerChildren)
|
||||
{
|
||||
if (child.getItemId() != -1 && !child.isHidden())
|
||||
{
|
||||
// calculate correct item position as if this was a normal tab
|
||||
int adjYOffset = (items / ITEMS_PER_ROW) * ITEM_VERTICAL_SPACING;
|
||||
int adjXOffset = (items % ITEMS_PER_ROW) * ITEM_HORIZONTAL_SPACING + ITEM_ROW_START;
|
||||
|
||||
if (child.getOriginalY() != adjYOffset)
|
||||
{
|
||||
child.setOriginalY(adjYOffset);
|
||||
child.revalidate();
|
||||
}
|
||||
|
||||
if (child.getOriginalX() != adjXOffset)
|
||||
{
|
||||
child.setOriginalX(adjXOffset);
|
||||
child.revalidate();
|
||||
}
|
||||
|
||||
items++;
|
||||
}
|
||||
|
||||
// separator line or tab text
|
||||
if (child.getSpriteId() == SpriteID.RESIZEABLE_MODE_SIDE_PANEL_BACKGROUND
|
||||
|| child.getText().contains("Tab"))
|
||||
{
|
||||
child.setHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
final Widget bankItemContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
|
||||
int itemContainerHeight = bankItemContainer.getHeight();
|
||||
// add a second row of height here to allow users to scroll down when the last row is partially visible
|
||||
int adjustedScrollHeight = (items / ITEMS_PER_ROW) * ITEM_VERTICAL_SPACING + ITEM_VERTICAL_SPACING;
|
||||
itemContainer.setScrollHeight(Math.max(adjustedScrollHeight, itemContainerHeight));
|
||||
|
||||
final int itemContainerScroll = bankItemContainer.getScrollY();
|
||||
clientThread.invokeLater(() ->
|
||||
client.runScript(ScriptID.UPDATE_SCROLLBAR,
|
||||
WidgetInfo.BANK_SCROLLBAR.getId(),
|
||||
WidgetInfo.BANK_ITEM_CONTAINER.getId(),
|
||||
itemContainerScroll));
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
tabInterface.update();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onDraggingWidgetChanged(DraggingWidgetChanged event)
|
||||
{
|
||||
final boolean shiftPressed = client.isKeyPressed(KeyCode.KC_SHIFT);
|
||||
tabInterface.handleDrag(event.isDraggingWidget(), shiftPressed);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded event)
|
||||
{
|
||||
if (event.getGroupId() == WidgetID.BANK_GROUP_ID)
|
||||
{
|
||||
tabInterface.init();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseWheelEvent mouseWheelMoved(MouseWheelEvent event)
|
||||
{
|
||||
tabInterface.handleWheel(event);
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.banktags;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.ItemVariationMapping;
|
||||
import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP;
|
||||
import net.runelite.client.plugins.cluescrolls.ClueScrollService;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.ClueScroll;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.CoordinateClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.EmoteClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.FairyRingClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.HotColdClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.MapClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.item.ItemRequirement;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Singleton
|
||||
public class TagManager
|
||||
{
|
||||
static final String ITEM_KEY_PREFIX = "item_";
|
||||
private final ConfigManager configManager;
|
||||
private final ItemManager itemManager;
|
||||
private final ClueScrollService clueScrollService;
|
||||
|
||||
@Inject
|
||||
private TagManager(
|
||||
final ItemManager itemManager,
|
||||
final ConfigManager configManager,
|
||||
final ClueScrollService clueScrollService)
|
||||
{
|
||||
this.itemManager = itemManager;
|
||||
this.configManager = configManager;
|
||||
this.clueScrollService = clueScrollService;
|
||||
}
|
||||
|
||||
String getTagString(int itemId, boolean variation)
|
||||
{
|
||||
itemId = getItemId(itemId, variation);
|
||||
|
||||
String config = configManager.getConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
||||
if (config == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
Collection<String> getTags(int itemId, boolean variation)
|
||||
{
|
||||
return new LinkedHashSet<>(Text.fromCSV(getTagString(itemId, variation).toLowerCase()));
|
||||
}
|
||||
|
||||
void setTagString(int itemId, String tags, boolean variation)
|
||||
{
|
||||
itemId = getItemId(itemId, variation);
|
||||
|
||||
if (Strings.isNullOrEmpty(tags))
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId, tags);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTags(int itemId, final Collection<String> t, boolean variation)
|
||||
{
|
||||
final Collection<String> tags = getTags(itemId, variation);
|
||||
if (tags.addAll(t))
|
||||
{
|
||||
setTags(itemId, tags, variation);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTag(int itemId, String tag, boolean variation)
|
||||
{
|
||||
final Collection<String> tags = getTags(itemId, variation);
|
||||
if (tags.add(Text.standardize(tag)))
|
||||
{
|
||||
setTags(itemId, tags, variation);
|
||||
}
|
||||
}
|
||||
|
||||
private void setTags(int itemId, Collection<String> tags, boolean variation)
|
||||
{
|
||||
setTagString(itemId, Text.toCSV(tags), variation);
|
||||
}
|
||||
|
||||
boolean findTag(int itemId, String search)
|
||||
{
|
||||
if (search.equals("clue") && testClue(itemId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Collection<String> tags = getTags(itemId, false);
|
||||
tags.addAll(getTags(itemId, true));
|
||||
return tags.stream().anyMatch(tag -> tag.startsWith(Text.standardize(search)));
|
||||
}
|
||||
|
||||
public List<Integer> getItemsForTag(String tag)
|
||||
{
|
||||
final String prefix = CONFIG_GROUP + "." + ITEM_KEY_PREFIX;
|
||||
return configManager.getConfigurationKeys(prefix).stream()
|
||||
.map(item -> Integer.parseInt(item.replace(prefix, "")))
|
||||
.filter(item -> getTags(item, false).contains(tag) || getTags(item, true).contains(tag))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void removeTag(String tag)
|
||||
{
|
||||
final String prefix = CONFIG_GROUP + "." + ITEM_KEY_PREFIX;
|
||||
configManager.getConfigurationKeys(prefix).forEach(item ->
|
||||
{
|
||||
int id = Integer.parseInt(item.replace(prefix, ""));
|
||||
removeTag(id, tag);
|
||||
});
|
||||
}
|
||||
|
||||
public void removeTag(int itemId, String tag)
|
||||
{
|
||||
Collection<String> tags = getTags(itemId, false);
|
||||
if (tags.remove(Text.standardize(tag)))
|
||||
{
|
||||
setTags(itemId, tags, false);
|
||||
}
|
||||
|
||||
tags = getTags(itemId, true);
|
||||
if (tags.remove(Text.standardize(tag)))
|
||||
{
|
||||
setTags(itemId, tags, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void renameTag(String oldTag, String newTag)
|
||||
{
|
||||
List<Integer> items = getItemsForTag(Text.standardize(oldTag));
|
||||
items.forEach(id ->
|
||||
{
|
||||
Collection<String> tags = getTags(id, id < 0);
|
||||
|
||||
tags.remove(Text.standardize(oldTag));
|
||||
tags.add(Text.standardize(newTag));
|
||||
|
||||
setTags(id, tags, id < 0);
|
||||
});
|
||||
}
|
||||
|
||||
private int getItemId(int itemId, boolean variation)
|
||||
{
|
||||
itemId = Math.abs(itemId);
|
||||
itemId = itemManager.canonicalize(itemId);
|
||||
|
||||
if (variation)
|
||||
{
|
||||
itemId = ItemVariationMapping.map(itemId) * -1;
|
||||
}
|
||||
|
||||
return itemId;
|
||||
}
|
||||
|
||||
private boolean testClue(int itemId)
|
||||
{
|
||||
ClueScroll c = clueScrollService.getClue();
|
||||
|
||||
if (c == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c instanceof EmoteClue)
|
||||
{
|
||||
EmoteClue emote = (EmoteClue) c;
|
||||
|
||||
for (ItemRequirement ir : emote.getItemRequirements())
|
||||
{
|
||||
if (ir.fulfilledBy(itemId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c instanceof CoordinateClue || c instanceof HotColdClue || c instanceof FairyRingClue)
|
||||
{
|
||||
return itemId == ItemID.SPADE;
|
||||
}
|
||||
else if (c instanceof MapClue)
|
||||
{
|
||||
MapClue mapClue = (MapClue) c;
|
||||
|
||||
return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.banktags.tabs;
|
||||
|
||||
class MenuIndexes
|
||||
{
|
||||
static class NewTab
|
||||
{
|
||||
static final int NEW_TAB = 2;
|
||||
static final int IMPORT_TAB = 3;
|
||||
static final int OPEN_TAB_MENU = 4;
|
||||
}
|
||||
|
||||
static class Tab
|
||||
{
|
||||
static final int OPEN_TAG = 2;
|
||||
static final int CHANGE_ICON = 3;
|
||||
static final int DELETE_TAB = 4;
|
||||
static final int EXPORT_TAB = 5;
|
||||
static final int RENAME_TAB = 6;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.banktags.tabs;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP;
|
||||
import static net.runelite.client.plugins.banktags.BankTagsPlugin.ICON_SEARCH;
|
||||
import static net.runelite.client.plugins.banktags.BankTagsPlugin.TAG_TABS_CONFIG;
|
||||
import net.runelite.client.util.Text;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
@Singleton
|
||||
class TabManager
|
||||
{
|
||||
@Getter
|
||||
private final List<TagTab> tabs = new ArrayList<>();
|
||||
private final ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private TabManager(ConfigManager configManager)
|
||||
{
|
||||
this.configManager = configManager;
|
||||
}
|
||||
|
||||
void add(TagTab tagTab)
|
||||
{
|
||||
if (!contains(tagTab.getTag()))
|
||||
{
|
||||
tabs.add(tagTab);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
tabs.forEach(t -> t.setHidden(true));
|
||||
tabs.clear();
|
||||
}
|
||||
|
||||
TagTab find(String tag)
|
||||
{
|
||||
Optional<TagTab> first = tabs.stream().filter(t -> t.getTag().equals(Text.standardize(tag))).findAny();
|
||||
return first.orElse(null);
|
||||
}
|
||||
|
||||
List<String> getAllTabs()
|
||||
{
|
||||
return Text.fromCSV(MoreObjects.firstNonNull(configManager.getConfiguration(CONFIG_GROUP, TAG_TABS_CONFIG), ""));
|
||||
}
|
||||
|
||||
TagTab load(String tag)
|
||||
{
|
||||
TagTab tagTab = find(tag);
|
||||
|
||||
if (tagTab == null)
|
||||
{
|
||||
tag = Text.standardize(tag);
|
||||
String item = configManager.getConfiguration(CONFIG_GROUP, ICON_SEARCH + tag);
|
||||
int itemid = NumberUtils.toInt(item, ItemID.SPADE);
|
||||
tagTab = new TagTab(itemid, tag);
|
||||
}
|
||||
|
||||
return tagTab;
|
||||
}
|
||||
|
||||
void swap(String tagToMove, String tagDestination)
|
||||
{
|
||||
tagToMove = Text.standardize(tagToMove);
|
||||
tagDestination = Text.standardize(tagDestination);
|
||||
|
||||
if (contains(tagToMove) && contains(tagDestination))
|
||||
{
|
||||
Collections.swap(tabs, indexOf(tagToMove), indexOf(tagDestination));
|
||||
}
|
||||
}
|
||||
|
||||
void insert(String tagToMove, String tagDestination)
|
||||
{
|
||||
tagToMove = Text.standardize(tagToMove);
|
||||
tagDestination = Text.standardize(tagDestination);
|
||||
|
||||
if (contains(tagToMove) && contains(tagDestination))
|
||||
{
|
||||
tabs.add(indexOf(tagDestination), tabs.remove(indexOf(tagToMove)));
|
||||
}
|
||||
}
|
||||
|
||||
void remove(String tag)
|
||||
{
|
||||
TagTab tagTab = find(tag);
|
||||
|
||||
if (tagTab != null)
|
||||
{
|
||||
tagTab.setHidden(true);
|
||||
tabs.remove(tagTab);
|
||||
removeIcon(tag);
|
||||
}
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
String tags = Text.toCSV(tabs.stream().map(TagTab::getTag).collect(Collectors.toList()));
|
||||
configManager.setConfiguration(CONFIG_GROUP, TAG_TABS_CONFIG, tags);
|
||||
}
|
||||
|
||||
void removeIcon(final String tag)
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, ICON_SEARCH + Text.standardize(tag));
|
||||
}
|
||||
|
||||
void setIcon(final String tag, final String icon)
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, ICON_SEARCH + Text.standardize(tag), icon);
|
||||
}
|
||||
|
||||
int size()
|
||||
{
|
||||
return tabs.size();
|
||||
}
|
||||
|
||||
private boolean contains(String tag)
|
||||
{
|
||||
return tabs.stream().anyMatch(t -> t.getTag().equals(tag));
|
||||
}
|
||||
|
||||
private int indexOf(TagTab tagTab)
|
||||
{
|
||||
return tabs.indexOf(tagTab);
|
||||
}
|
||||
|
||||
private int indexOf(String tag)
|
||||
{
|
||||
return indexOf(find(tag));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.banktags.tabs;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.runelite.client.game.SpriteOverride;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum TabSprites implements SpriteOverride
|
||||
{
|
||||
INCINERATOR(-200, "incinerator.png"),
|
||||
TAB_BACKGROUND(-201, "tag-tab.png"),
|
||||
TAB_BACKGROUND_ACTIVE(-202, "tag-tab-active.png"),
|
||||
UP_ARROW(-203, "up-arrow.png"),
|
||||
DOWN_ARROW(-204, "down-arrow.png"),
|
||||
NEW_TAB(-205, "new-tab.png");
|
||||
|
||||
@Getter
|
||||
private final int spriteId;
|
||||
|
||||
@Getter
|
||||
private final String fileName;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.banktags.tabs;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(of = "tag")
|
||||
public class TagTab
|
||||
{
|
||||
private String tag;
|
||||
private int iconItemId;
|
||||
private Widget background;
|
||||
private Widget icon;
|
||||
private Widget menu;
|
||||
|
||||
TagTab(int iconItemId, String tag)
|
||||
{
|
||||
this.iconItemId = iconItemId;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
void setHidden(boolean hide)
|
||||
{
|
||||
if (background != null)
|
||||
{
|
||||
background.setHidden(hide);
|
||||
}
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
icon.setHidden(hide);
|
||||
}
|
||||
|
||||
if (menu != null)
|
||||
{
|
||||
menu.setHidden(hide);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,8 +53,8 @@ import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.vars.InputType;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getChildFromID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
@@ -203,8 +203,8 @@ public class ChatHistoryPlugin extends Plugin implements KeyListener
|
||||
return;
|
||||
}
|
||||
|
||||
final int groupId = TO_GROUP(entry.getParam1());
|
||||
final int childId = TO_CHILD(entry.getParam1());
|
||||
final int groupId = getGroupFromID(entry.getParam1());
|
||||
final int childId = getChildFromID(entry.getParam1());
|
||||
|
||||
if (groupId != WidgetInfo.CHATBOX.getGroupId())
|
||||
{
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Joris K <kjorisje@gmail.com>
|
||||
* Copyright (c) 2018, Lasse <cronick@zytex.dk>
|
||||
* 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.cooking;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Units;
|
||||
|
||||
@ConfigGroup("cooking")
|
||||
public interface CookingConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "statTimeout",
|
||||
name = "Reset stats",
|
||||
description = "Configures the time until the session resets and the overlay is hidden (0 = Disable feature)"
|
||||
)
|
||||
@Units(Units.MINUTES)
|
||||
default int statTimeout()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "fermentTimer",
|
||||
name = "Show wine ferment timer",
|
||||
description = "Configures if the timer before wines are fermented is shown"
|
||||
)
|
||||
default boolean fermentTimer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Joris K <kjorisje@gmail.com>
|
||||
* Copyright (c) 2018, Lasse <cronick@zytex.dk>
|
||||
* 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.cooking;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.text.DecimalFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import static net.runelite.api.AnimationID.COOKING_FIRE;
|
||||
import static net.runelite.api.AnimationID.COOKING_RANGE;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerService;
|
||||
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.OverlayPanel;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
|
||||
class CookingOverlay extends OverlayPanel
|
||||
{
|
||||
private static final int COOK_TIMEOUT = 3;
|
||||
private static final DecimalFormat FORMAT = new DecimalFormat("#.#");
|
||||
static final String COOKING_RESET = "Reset";
|
||||
|
||||
private final Client client;
|
||||
private final CookingPlugin plugin;
|
||||
private final XpTrackerService xpTrackerService;
|
||||
|
||||
@Inject
|
||||
private CookingOverlay(Client client, CookingPlugin plugin, XpTrackerService xpTrackerService)
|
||||
{
|
||||
super(plugin);
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.xpTrackerService = xpTrackerService;
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Cooking overlay"));
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY, COOKING_RESET, "Cooking overlay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
CookingSession session = plugin.getSession();
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isCooking() || Duration.between(session.getLastCookingAction(), Instant.now()).getSeconds() < COOK_TIMEOUT)
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("Cooking")
|
||||
.color(Color.GREEN)
|
||||
.build());
|
||||
}
|
||||
else
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("NOT cooking")
|
||||
.color(Color.RED)
|
||||
.build());
|
||||
}
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Cooked:")
|
||||
.right(session.getCookAmount() + (session.getCookAmount() >= 1 ? " (" + xpTrackerService.getActionsHr(Skill.COOKING) + "/hr)" : ""))
|
||||
.build());
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Burnt:")
|
||||
.right(session.getBurnAmount() + (session.getBurnAmount() >= 1 ? " (" + FORMAT.format(session.getBurntPercentage()) + "%)" : ""))
|
||||
.build());
|
||||
|
||||
return super.render(graphics);
|
||||
}
|
||||
|
||||
private boolean isCooking()
|
||||
{
|
||||
switch (client.getLocalPlayer().getAnimation())
|
||||
{
|
||||
case COOKING_FIRE:
|
||||
case COOKING_RANGE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Joris K <kjorisje@gmail.com>
|
||||
* Copyright (c) 2018, Lasse <cronick@zytex.dk>
|
||||
* 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.cooking;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.GraphicChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.OverlayMenuClicked;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Cooking",
|
||||
description = "Show cooking statistics",
|
||||
tags = {"overlay", "skilling", "cook"}
|
||||
)
|
||||
@PluginDependency(XpTrackerPlugin.class)
|
||||
public class CookingPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private CookingConfig config;
|
||||
|
||||
@Inject
|
||||
private CookingOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private CookingSession session;
|
||||
|
||||
@Provides
|
||||
CookingConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(CookingConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
session = null;
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
infoBoxManager.removeIf(FermentTimer.class::isInstance);
|
||||
overlayManager.remove(overlay);
|
||||
session = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onOverlayMenuClicked(OverlayMenuClicked overlayMenuClicked)
|
||||
{
|
||||
OverlayMenuEntry overlayMenuEntry = overlayMenuClicked.getEntry();
|
||||
if (overlayMenuEntry.getMenuAction() == MenuAction.RUNELITE_OVERLAY
|
||||
&& overlayMenuClicked.getEntry().getOption().equals(CookingOverlay.COOKING_RESET)
|
||||
&& overlayMenuClicked.getOverlay() == overlay)
|
||||
{
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick gameTick)
|
||||
{
|
||||
if (session == null || config.statTimeout() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
Duration sinceCut = Duration.between(session.getLastCookingAction(), Instant.now());
|
||||
|
||||
if (sinceCut.compareTo(statTimeout) >= 0)
|
||||
{
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGraphicChanged(GraphicChanged graphicChanged)
|
||||
{
|
||||
Player player = client.getLocalPlayer();
|
||||
|
||||
if (graphicChanged.getActor() != player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.getGraphic() == GraphicID.WINE_MAKE && config.fermentTimer())
|
||||
{
|
||||
Optional<FermentTimer> fermentTimerOpt = infoBoxManager.getInfoBoxes().stream()
|
||||
.filter(FermentTimer.class::isInstance)
|
||||
.map(FermentTimer.class::cast)
|
||||
.findAny();
|
||||
|
||||
if (fermentTimerOpt.isPresent())
|
||||
{
|
||||
FermentTimer fermentTimer = fermentTimerOpt.get();
|
||||
fermentTimer.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
FermentTimer fermentTimer = new FermentTimer(itemManager.getImage(ItemID.JUG_OF_WINE), this);
|
||||
infoBoxManager.addInfoBox(fermentTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (event.getType() != ChatMessageType.SPAM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final String message = event.getMessage();
|
||||
|
||||
if (message.startsWith("You successfully cook")
|
||||
|| message.startsWith("You successfully bake")
|
||||
|| message.startsWith("You manage to cook")
|
||||
|| message.startsWith("You roast a")
|
||||
|| message.startsWith("You cook")
|
||||
|| message.startsWith("You dry a piece of meat"))
|
||||
{
|
||||
if (session == null)
|
||||
{
|
||||
session = new CookingSession();
|
||||
}
|
||||
|
||||
session.updateLastCookingAction();
|
||||
session.increaseCookAmount();
|
||||
|
||||
}
|
||||
else if (message.startsWith("You accidentally burn")
|
||||
|| message.startsWith("You accidentally spoil"))
|
||||
{
|
||||
if (session == null)
|
||||
{
|
||||
session = new CookingSession();
|
||||
}
|
||||
|
||||
session.updateLastCookingAction();
|
||||
session.increaseBurnAmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Joris K <kjorisje@gmail.com>
|
||||
* Copyright (c) 2018, Lasse <cronick@zytex.dk>
|
||||
* 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.cooking;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
class CookingSession
|
||||
{
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Instant lastCookingAction;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int cookAmount;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int burnAmount;
|
||||
|
||||
void updateLastCookingAction()
|
||||
{
|
||||
this.lastCookingAction = Instant.now();
|
||||
}
|
||||
|
||||
void increaseCookAmount()
|
||||
{
|
||||
this.cookAmount++;
|
||||
}
|
||||
|
||||
void increaseBurnAmount()
|
||||
{
|
||||
this.burnAmount++;
|
||||
}
|
||||
|
||||
double getBurntPercentage()
|
||||
{
|
||||
return ((double) getBurnAmount() / (getCookAmount() + getBurnAmount())) * 100;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.cooking;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBox;
|
||||
|
||||
final class FermentTimer extends InfoBox
|
||||
{
|
||||
private static final Duration FERMENT_TIME = Duration.ofMillis(13_800);
|
||||
|
||||
private Instant fermentTime;
|
||||
|
||||
FermentTimer(BufferedImage image, Plugin plugin)
|
||||
{
|
||||
super(image, plugin);
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
int seconds = timeUntilFerment();
|
||||
return Integer.toString(seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getTextColor()
|
||||
{
|
||||
int seconds = timeUntilFerment();
|
||||
return seconds <= 3 ? Color.RED : Color.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cull()
|
||||
{
|
||||
int seconds = timeUntilFerment();
|
||||
return seconds <= 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
fermentTime = Instant.now().plus(FERMENT_TIME);
|
||||
}
|
||||
|
||||
private int timeUntilFerment()
|
||||
{
|
||||
return (int) Duration.between(Instant.now(), fermentTime).getSeconds();
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,8 @@ import net.runelite.api.events.ScriptPostFired;
|
||||
import net.runelite.api.events.ScriptPreFired;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getChildFromID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
@@ -120,7 +120,7 @@ public class ScriptInspector extends JFrame
|
||||
if (source != null)
|
||||
{
|
||||
int id = source.getId();
|
||||
output += " - " + TO_GROUP(id) + "." + TO_CHILD(id);
|
||||
output += " - " + getGroupFromID(id) + "." + getChildFromID(id);
|
||||
|
||||
if (source.getIndex() != -1)
|
||||
{
|
||||
|
||||
@@ -59,8 +59,8 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.SpriteID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getChildFromID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
@@ -464,7 +464,7 @@ class WidgetInspector extends JFrame
|
||||
|
||||
picker = parent.createChild(-1, WidgetType.GRAPHIC);
|
||||
|
||||
log.info("Picker is {}.{} [{}]", WidgetInfo.TO_GROUP(picker.getId()), WidgetInfo.TO_CHILD(picker.getId()), picker.getIndex());
|
||||
log.info("Picker is {}.{} [{}]", WidgetInfo.getGroupFromID(picker.getId()), WidgetInfo.getChildFromID(picker.getId()), picker.getIndex());
|
||||
|
||||
picker.setSpriteId(SpriteID.MOBILE_FINGER_ON_INTERFACE);
|
||||
picker.setOriginalWidth(15);
|
||||
@@ -538,7 +538,7 @@ class WidgetInspector extends JFrame
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String name = WidgetInfo.TO_GROUP(entry.getParam1()) + "." + WidgetInfo.TO_CHILD(entry.getParam1());
|
||||
String name = WidgetInfo.getGroupFromID(entry.getParam1()) + "." + WidgetInfo.getChildFromID(entry.getParam1());
|
||||
|
||||
if (entry.getParam0() != -1)
|
||||
{
|
||||
@@ -584,7 +584,7 @@ class WidgetInspector extends JFrame
|
||||
public static String getWidgetIdentifier(Widget widget)
|
||||
{
|
||||
int id = widget.getId();
|
||||
String str = TO_GROUP(id) + "." + TO_CHILD(id);
|
||||
String str = getGroupFromID(id) + "." + getChildFromID(id);
|
||||
|
||||
if (widget.getIndex() != -1)
|
||||
{
|
||||
|
||||
@@ -45,8 +45,8 @@ import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import static net.runelite.api.widgets.WidgetInfo.SEED_VAULT_ITEM_CONTAINER;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getChildFromID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
@@ -123,8 +123,8 @@ public class ExaminePlugin extends Plugin
|
||||
id = event.getId();
|
||||
|
||||
int widgetId = event.getWidgetId();
|
||||
int widgetGroup = TO_GROUP(widgetId);
|
||||
int widgetChild = TO_CHILD(widgetId);
|
||||
int widgetGroup = getGroupFromID(widgetId);
|
||||
int widgetChild = getChildFromID(widgetId);
|
||||
Widget widget = client.getWidget(widgetGroup, widgetChild);
|
||||
WidgetItem widgetItem = widget.getWidgetItem(event.getActionParam());
|
||||
quantity = widgetItem != null && widgetItem.getId() >= 0 ? widgetItem.getQuantity() : 1;
|
||||
@@ -266,8 +266,8 @@ public class ExaminePlugin extends Plugin
|
||||
|
||||
private int[] findItemFromWidget(int widgetId, int actionParam)
|
||||
{
|
||||
int widgetGroup = TO_GROUP(widgetId);
|
||||
int widgetChild = TO_CHILD(widgetId);
|
||||
int widgetGroup = getGroupFromID(widgetId);
|
||||
int widgetChild = getChildFromID(widgetId);
|
||||
Widget widget = client.getWidget(widgetGroup, widgetChild);
|
||||
|
||||
if (widget == null)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.experiencedrop;
|
||||
|
||||
enum PrayerType
|
||||
{
|
||||
MELEE,
|
||||
RANGE,
|
||||
MAGIC;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
|
||||
* 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.experiencedrop;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Units;
|
||||
|
||||
@ConfigGroup("xpdrop")
|
||||
public interface XpDropConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "hideSkillIcons",
|
||||
name = "Hide skill icons",
|
||||
description = "Configure if XP drops will show their respective skill icons",
|
||||
position = 0
|
||||
)
|
||||
default boolean hideSkillIcons()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "meleePrayerColor",
|
||||
name = "Melee Prayer Color",
|
||||
description = "XP drop color when a melee prayer is active",
|
||||
position = 1
|
||||
)
|
||||
default Color getMeleePrayerColor()
|
||||
{
|
||||
return new Color(0x15, 0x80, 0xAD);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "rangePrayerColor",
|
||||
name = "Range Prayer Color",
|
||||
description = "XP drop color when a range prayer is active",
|
||||
position = 2
|
||||
)
|
||||
default Color getRangePrayerColor()
|
||||
{
|
||||
return new Color(0x15, 0x80, 0xAD);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "magePrayerColor",
|
||||
name = "Mage Prayer Color",
|
||||
description = "XP drop color when a mage prayer is active",
|
||||
position = 3
|
||||
)
|
||||
default Color getMagePrayerColor()
|
||||
{
|
||||
return new Color(0x15, 0x80, 0xAD);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "fakeXpDropDelay",
|
||||
name = "Fake Xp Drop delay",
|
||||
description = "Configures how many ticks should pass between fake XP drops, 0 to disable",
|
||||
position = 4
|
||||
)
|
||||
@Units(Units.TICKS)
|
||||
default int fakeXpDropDelay()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Cameron <https://github.com/noremac201>, SoyChai <https://github.com/SoyChai>
|
||||
* 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.experiencedrop;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.EnumComposition;
|
||||
import net.runelite.api.EnumID;
|
||||
import static net.runelite.api.ScriptID.XPDROPS_SETDROPSIZE;
|
||||
import static net.runelite.api.ScriptID.XPDROP_DISABLED;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ScriptPreFired;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "XP Drop",
|
||||
description = "Enable customization of the way XP drops are displayed",
|
||||
tags = {"experience", "levels", "tick", "prayer", "xpdrop"}
|
||||
)
|
||||
public class XpDropPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private XpDropConfig config;
|
||||
|
||||
private int tickCounter = 0;
|
||||
private int previousExpGained;
|
||||
private boolean hasDropped = false;
|
||||
private boolean correctPrayer;
|
||||
private Skill lastSkill = null;
|
||||
private final Map<Skill, Integer> previousSkillExpTable = new EnumMap<>(Skill.class);
|
||||
|
||||
@Provides
|
||||
XpDropConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(XpDropConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptPreFired(ScriptPreFired scriptPreFired)
|
||||
{
|
||||
if (scriptPreFired.getScriptId() == XPDROPS_SETDROPSIZE)
|
||||
{
|
||||
final int[] intStack = client.getIntStack();
|
||||
final int intStackSize = client.getIntStackSize();
|
||||
// This runs prior to the proc being invoked, so the arguments are still on the stack.
|
||||
// Grab the first argument to the script.
|
||||
final int widgetId = intStack[intStackSize - 4];
|
||||
processXpDrop(widgetId);
|
||||
}
|
||||
}
|
||||
|
||||
private void processXpDrop(int widgetId)
|
||||
{
|
||||
final Widget xpdrop = client.getWidget(widgetId);
|
||||
final Widget[] children = xpdrop.getChildren();
|
||||
// child 0 is the xpdrop text, everything else are sprite ids for skills
|
||||
final Widget text = children[0];
|
||||
|
||||
PrayerType prayer = getActivePrayerType();
|
||||
if (prayer == null)
|
||||
{
|
||||
hideSkillIcons(xpdrop);
|
||||
resetTextColor(text);
|
||||
return;
|
||||
}
|
||||
|
||||
final IntStream spriteIDs =
|
||||
Arrays.stream(children)
|
||||
.skip(1) // skip text
|
||||
.filter(Objects::nonNull)
|
||||
.mapToInt(Widget::getSpriteId);
|
||||
|
||||
int color = 0;
|
||||
|
||||
switch (prayer)
|
||||
{
|
||||
case MELEE:
|
||||
if (correctPrayer || spriteIDs.anyMatch(id ->
|
||||
id == SpriteID.SKILL_ATTACK || id == SpriteID.SKILL_STRENGTH || id == SpriteID.SKILL_DEFENCE))
|
||||
{
|
||||
color = config.getMeleePrayerColor().getRGB();
|
||||
correctPrayer = true;
|
||||
}
|
||||
break;
|
||||
case RANGE:
|
||||
if (correctPrayer || spriteIDs.anyMatch(id -> id == SpriteID.SKILL_RANGED))
|
||||
{
|
||||
color = config.getRangePrayerColor().getRGB();
|
||||
correctPrayer = true;
|
||||
}
|
||||
break;
|
||||
case MAGIC:
|
||||
if (correctPrayer || spriteIDs.anyMatch(id -> id == SpriteID.SKILL_MAGIC))
|
||||
{
|
||||
color = config.getMagePrayerColor().getRGB();
|
||||
correctPrayer = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (color != 0)
|
||||
{
|
||||
text.setTextColor(color);
|
||||
}
|
||||
else
|
||||
{
|
||||
resetTextColor(text);
|
||||
}
|
||||
|
||||
hideSkillIcons(xpdrop);
|
||||
}
|
||||
|
||||
private void resetTextColor(Widget widget)
|
||||
{
|
||||
EnumComposition colorEnum = client.getEnum(EnumID.XPDROP_COLORS);
|
||||
int defaultColorId = client.getVar(Varbits.EXPERIENCE_DROP_COLOR);
|
||||
int color = colorEnum.getIntValue(defaultColorId);
|
||||
widget.setTextColor(color);
|
||||
}
|
||||
|
||||
private void hideSkillIcons(Widget xpdrop)
|
||||
{
|
||||
if (config.hideSkillIcons())
|
||||
{
|
||||
Widget[] children = xpdrop.getChildren();
|
||||
// keep only text
|
||||
Arrays.fill(children, 1, children.length, null);
|
||||
}
|
||||
}
|
||||
|
||||
private PrayerType getActivePrayerType()
|
||||
{
|
||||
for (XpPrayer prayer : XpPrayer.values())
|
||||
{
|
||||
if (client.isPrayerActive(prayer.getPrayer()))
|
||||
{
|
||||
return prayer.getType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick tick)
|
||||
{
|
||||
correctPrayer = false;
|
||||
|
||||
final int fakeTickDelay = config.fakeXpDropDelay();
|
||||
|
||||
if (fakeTickDelay == 0 || lastSkill == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If an xp drop was created this tick, reset the counter
|
||||
if (hasDropped)
|
||||
{
|
||||
hasDropped = false;
|
||||
tickCounter = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (++tickCounter % fakeTickDelay != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
client.runScript(XPDROP_DISABLED, lastSkill.ordinal(), previousExpGained);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatChanged(StatChanged statChanged)
|
||||
{
|
||||
final Skill skill = statChanged.getSkill();
|
||||
final int xp = statChanged.getXp();
|
||||
|
||||
lastSkill = skill;
|
||||
|
||||
Integer previous = previousSkillExpTable.put(skill, xp);
|
||||
if (previous != null)
|
||||
{
|
||||
previousExpGained = xp - previous;
|
||||
hasDropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.experiencedrop;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Prayer;
|
||||
import static net.runelite.api.Prayer.*;
|
||||
import static net.runelite.client.plugins.experiencedrop.PrayerType.MAGIC;
|
||||
import static net.runelite.client.plugins.experiencedrop.PrayerType.MELEE;
|
||||
import static net.runelite.client.plugins.experiencedrop.PrayerType.RANGE;
|
||||
|
||||
enum XpPrayer
|
||||
{
|
||||
XP_BURST_OF_STRENGTH(BURST_OF_STRENGTH, MELEE),
|
||||
XP_CLARITY_OF_THOUGHT(CLARITY_OF_THOUGHT, MELEE),
|
||||
XP_SHARP_EYE(SHARP_EYE, RANGE),
|
||||
XP_MYSTIC_WILL(MYSTIC_WILL, MAGIC),
|
||||
XP_SUPERHUMAN_STRENGTH(SUPERHUMAN_STRENGTH, MELEE),
|
||||
XP_IMPROVED_REFLEXES(IMPROVED_REFLEXES, MELEE),
|
||||
XP_HAWK_EYE(HAWK_EYE, RANGE),
|
||||
XP_MYSTIC_LORE(MYSTIC_LORE, MAGIC),
|
||||
XP_ULTIMATE_STRENGTH(ULTIMATE_STRENGTH, MELEE),
|
||||
XP_INCREDIBLE_REFLEXES(INCREDIBLE_REFLEXES, MELEE),
|
||||
XP_EAGLE_EYE(EAGLE_EYE, RANGE),
|
||||
XP_MYSTIC_MIGHT(MYSTIC_MIGHT, MAGIC),
|
||||
XP_CHIVALRY(CHIVALRY, MELEE),
|
||||
XP_PIETY(PIETY, MELEE),
|
||||
XP_RIGOUR(RIGOUR, RANGE),
|
||||
XP_AUGURY(AUGURY, MAGIC);
|
||||
|
||||
@Getter
|
||||
private final Prayer prayer;
|
||||
@Getter
|
||||
private final PrayerType type;
|
||||
|
||||
XpPrayer(Prayer prayer, PrayerType type)
|
||||
{
|
||||
this.prayer = prayer;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Seth <Sethtroll3@gmail.com>
|
||||
* 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.fishing;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Units;
|
||||
|
||||
@ConfigGroup("fishing")
|
||||
public interface FishingConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "onlyCurrent",
|
||||
name = "Display only currently fished fish",
|
||||
description = "Configures whether only current fished fish's fishing spots are displayed"
|
||||
)
|
||||
default boolean onlyCurrentSpot()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "showTiles",
|
||||
name = "Display spot tiles",
|
||||
description = "Configures whether tiles for fishing spots are highlighted"
|
||||
)
|
||||
default boolean showSpotTiles()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "showIcons",
|
||||
name = "Display spot icons",
|
||||
description = "Configures whether icons for fishing spots are displayed"
|
||||
)
|
||||
default boolean showSpotIcons()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "showNames",
|
||||
name = "Display spot names",
|
||||
description = "Configures whether names for fishing spots are displayed"
|
||||
)
|
||||
default boolean showSpotNames()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "overlayColor",
|
||||
name = "Overlay Color",
|
||||
description = "Color of overlays",
|
||||
position = 4
|
||||
)
|
||||
default Color getOverlayColor()
|
||||
{
|
||||
return Color.CYAN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "minnowsOverlayColor",
|
||||
name = "Minnows Overlay Color",
|
||||
description = "Color of overlays for Minnows",
|
||||
position = 5
|
||||
)
|
||||
default Color getMinnowsOverlayColor()
|
||||
{
|
||||
return Color.RED;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "aerialOverlayColor",
|
||||
name = "Aerial Overlay Color",
|
||||
description = "Color of overlays when 1-tick aerial fishing",
|
||||
position = 6
|
||||
)
|
||||
default Color getAerialOverlayColor()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
keyName = "statTimeout",
|
||||
name = "Reset stats",
|
||||
description = "The time until fishing session data is reset in minutes."
|
||||
)
|
||||
@Units(Units.MINUTES)
|
||||
default int statTimeout()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "showFishingStats",
|
||||
name = "Show Fishing session stats",
|
||||
description = "Display the fishing session stats."
|
||||
)
|
||||
default boolean showFishingStats()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
keyName = "showMinnowOverlay",
|
||||
name = "Show Minnow Movement overlay",
|
||||
description = "Display the minnow progress pie overlay."
|
||||
)
|
||||
default boolean showMinnowOverlay()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
keyName = "trawlerNotification",
|
||||
name = "Trawler activity notification",
|
||||
description = "Send a notification when fishing trawler activity drops below 15%."
|
||||
)
|
||||
default boolean trawlerNotification()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 11,
|
||||
keyName = "trawlerTimer",
|
||||
name = "Trawler timer in MM:SS",
|
||||
description = "Trawler Timer will display a more accurate timer in MM:SS format."
|
||||
)
|
||||
default boolean trawlerTimer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Seth <Sethtroll3@gmail.com>
|
||||
* 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.fishing;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicID;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerService;
|
||||
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.OverlayPanel;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
|
||||
class FishingOverlay extends OverlayPanel
|
||||
{
|
||||
private static final String FISHING_SPOT = "Fishing spot";
|
||||
static final String FISHING_RESET = "Reset";
|
||||
|
||||
private static final Set<Integer> FISHING_ANIMATIONS = ImmutableSet.of(
|
||||
AnimationID.FISHING_BARBTAIL_HARPOON,
|
||||
AnimationID.FISHING_BAREHAND,
|
||||
AnimationID.FISHING_BAREHAND_CAUGHT_SHARK_1,
|
||||
AnimationID.FISHING_BAREHAND_CAUGHT_SHARK_2,
|
||||
AnimationID.FISHING_BAREHAND_CAUGHT_SWORDFISH_1,
|
||||
AnimationID.FISHING_BAREHAND_CAUGHT_SWORDFISH_2,
|
||||
AnimationID.FISHING_BAREHAND_CAUGHT_TUNA_1,
|
||||
AnimationID.FISHING_BAREHAND_CAUGHT_TUNA_2,
|
||||
AnimationID.FISHING_BAREHAND_WINDUP_1,
|
||||
AnimationID.FISHING_BAREHAND_WINDUP_2,
|
||||
AnimationID.FISHING_BIG_NET,
|
||||
AnimationID.FISHING_CAGE,
|
||||
AnimationID.FISHING_CRYSTAL_HARPOON,
|
||||
AnimationID.FISHING_DRAGON_HARPOON,
|
||||
AnimationID.FISHING_HARPOON,
|
||||
AnimationID.FISHING_INFERNAL_HARPOON,
|
||||
AnimationID.FISHING_TRAILBLAZER_HARPOON,
|
||||
AnimationID.FISHING_TRAILBLAZER_HARPOON_2,
|
||||
AnimationID.FISHING_KARAMBWAN,
|
||||
AnimationID.FISHING_NET,
|
||||
AnimationID.FISHING_OILY_ROD,
|
||||
AnimationID.FISHING_POLE_CAST,
|
||||
AnimationID.FISHING_PEARL_ROD,
|
||||
AnimationID.FISHING_PEARL_FLY_ROD,
|
||||
AnimationID.FISHING_PEARL_BARBARIAN_ROD,
|
||||
AnimationID.FISHING_PEARL_ROD_2,
|
||||
AnimationID.FISHING_PEARL_FLY_ROD_2,
|
||||
AnimationID.FISHING_PEARL_BARBARIAN_ROD_2,
|
||||
AnimationID.FISHING_PEARL_OILY_ROD);
|
||||
|
||||
private final Client client;
|
||||
private final FishingPlugin plugin;
|
||||
private final FishingConfig config;
|
||||
private final XpTrackerService xpTrackerService;
|
||||
|
||||
@Inject
|
||||
public FishingOverlay(Client client, FishingPlugin plugin, FishingConfig config, XpTrackerService xpTrackerService)
|
||||
{
|
||||
super(plugin);
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.xpTrackerService = xpTrackerService;
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Fishing overlay"));
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY, FISHING_RESET, "Fishing overlay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!config.showFishingStats() || plugin.getSession().getLastFishCaught() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (client.getLocalPlayer().getInteracting() != null
|
||||
&& client.getLocalPlayer().getInteracting().getName().contains(FISHING_SPOT)
|
||||
&& client.getLocalPlayer().getInteracting().getGraphic() != GraphicID.FLYING_FISH
|
||||
&& FISHING_ANIMATIONS.contains(client.getLocalPlayer().getAnimation()))
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("Fishing")
|
||||
.color(Color.GREEN)
|
||||
.build());
|
||||
}
|
||||
else
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("NOT fishing")
|
||||
.color(Color.RED)
|
||||
.build());
|
||||
}
|
||||
|
||||
int actions = xpTrackerService.getActions(Skill.FISHING);
|
||||
if (actions > 0)
|
||||
{
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Caught fish:")
|
||||
.right(Integer.toString(actions))
|
||||
.build());
|
||||
|
||||
if (actions > 2)
|
||||
{
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Fish/hr:")
|
||||
.right(Integer.toString(xpTrackerService.getActionsHr(Skill.FISHING)))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
return super.render(graphics);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Seth <Sethtroll3@gmail.com>
|
||||
* Copyright (c) 2018, Levi <me@levischuck.com>
|
||||
* 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.fishing;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
import net.runelite.api.events.ItemContainerChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.OverlayMenuClicked;
|
||||
import net.runelite.client.game.FishingSpot;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Fishing",
|
||||
description = "Show fishing stats and mark fishing spots",
|
||||
tags = {"overlay", "skilling"}
|
||||
)
|
||||
@PluginDependency(XpTrackerPlugin.class)
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class FishingPlugin extends Plugin
|
||||
{
|
||||
private static final int TRAWLER_SHIP_REGION_NORMAL = 7499;
|
||||
private static final int TRAWLER_SHIP_REGION_SINKING = 8011;
|
||||
private static final int TRAWLER_TIME_LIMIT_IN_SECONDS = 614;
|
||||
private static final int TRAWLER_ACTIVITY_THRESHOLD = Math.round(0.15f * 255);
|
||||
|
||||
private Instant trawlerStartTime;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final FishingSession session = new FishingSession();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Map<Integer, MinnowSpot> minnowSpots = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final List<NPC> fishingSpots = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private FishingSpot currentSpot;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private Notifier notifier;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private FishingConfig config;
|
||||
|
||||
@Inject
|
||||
private FishingOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private FishingSpotOverlay spotOverlay;
|
||||
|
||||
@Inject
|
||||
private FishingSpotMinimapOverlay fishingSpotMinimapOverlay;
|
||||
|
||||
private boolean trawlerNotificationSent;
|
||||
|
||||
@Provides
|
||||
FishingConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(FishingConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(spotOverlay);
|
||||
overlayManager.add(fishingSpotMinimapOverlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
spotOverlay.setHidden(true);
|
||||
fishingSpotMinimapOverlay.setHidden(true);
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(spotOverlay);
|
||||
overlayManager.remove(fishingSpotMinimapOverlay);
|
||||
fishingSpots.clear();
|
||||
minnowSpots.clear();
|
||||
trawlerNotificationSent = false;
|
||||
currentSpot = null;
|
||||
trawlerStartTime = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
GameState gameState = gameStateChanged.getGameState();
|
||||
if (gameState == GameState.CONNECTION_LOST || gameState == GameState.LOGIN_SCREEN || gameState == GameState.HOPPING)
|
||||
{
|
||||
fishingSpots.clear();
|
||||
minnowSpots.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onOverlayMenuClicked(OverlayMenuClicked overlayMenuClicked)
|
||||
{
|
||||
OverlayMenuEntry overlayMenuEntry = overlayMenuClicked.getEntry();
|
||||
if (overlayMenuEntry.getMenuAction() == MenuAction.RUNELITE_OVERLAY
|
||||
&& overlayMenuClicked.getEntry().getOption().equals(FishingOverlay.FISHING_RESET)
|
||||
&& overlayMenuClicked.getOverlay() == overlay)
|
||||
{
|
||||
session.setLastFishCaught(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onItemContainerChanged(ItemContainerChanged event)
|
||||
{
|
||||
if (event.getItemContainer() != client.getItemContainer(InventoryID.INVENTORY)
|
||||
&& event.getItemContainer() != client.getItemContainer(InventoryID.EQUIPMENT))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean showOverlays = session.getLastFishCaught() != null
|
||||
|| canPlayerFish(client.getItemContainer(InventoryID.INVENTORY))
|
||||
|| canPlayerFish(client.getItemContainer(InventoryID.EQUIPMENT));
|
||||
|
||||
if (!showOverlays)
|
||||
{
|
||||
currentSpot = null;
|
||||
}
|
||||
|
||||
spotOverlay.setHidden(!showOverlays);
|
||||
fishingSpotMinimapOverlay.setHidden(!showOverlays);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (event.getType() != ChatMessageType.SPAM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getMessage().contains("You catch a") || event.getMessage().contains("You catch some") ||
|
||||
event.getMessage().equals("Your cormorant returns with its catch."))
|
||||
{
|
||||
session.setLastFishCaught(Instant.now());
|
||||
spotOverlay.setHidden(false);
|
||||
fishingSpotMinimapOverlay.setHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onInteractingChanged(InteractingChanged event)
|
||||
{
|
||||
if (event.getSource() != client.getLocalPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Actor target = event.getTarget();
|
||||
|
||||
if (!(target instanceof NPC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final NPC npc = (NPC) target;
|
||||
FishingSpot spot = FishingSpot.findSpot(npc.getId());
|
||||
|
||||
if (spot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentSpot = spot;
|
||||
}
|
||||
|
||||
private boolean canPlayerFish(final ItemContainer itemContainer)
|
||||
{
|
||||
if (itemContainer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Item item : itemContainer.getItems())
|
||||
{
|
||||
switch (item.getId())
|
||||
{
|
||||
case ItemID.DRAGON_HARPOON:
|
||||
case ItemID.INFERNAL_HARPOON:
|
||||
case ItemID.INFERNAL_HARPOON_UNCHARGED:
|
||||
case ItemID.HARPOON:
|
||||
case ItemID.BARBTAIL_HARPOON:
|
||||
case ItemID.BIG_FISHING_NET:
|
||||
case ItemID.SMALL_FISHING_NET:
|
||||
case ItemID.SMALL_FISHING_NET_6209:
|
||||
case ItemID.FISHING_ROD:
|
||||
case ItemID.FLY_FISHING_ROD:
|
||||
case ItemID.PEARL_BARBARIAN_ROD:
|
||||
case ItemID.PEARL_FISHING_ROD:
|
||||
case ItemID.PEARL_FLY_FISHING_ROD:
|
||||
case ItemID.BARBARIAN_ROD:
|
||||
case ItemID.OILY_FISHING_ROD:
|
||||
case ItemID.LOBSTER_POT:
|
||||
case ItemID.KARAMBWAN_VESSEL:
|
||||
case ItemID.KARAMBWAN_VESSEL_3159:
|
||||
case ItemID.CORMORANTS_GLOVE:
|
||||
case ItemID.CORMORANTS_GLOVE_22817:
|
||||
case ItemID.TRAILBLAZER_HARPOON:
|
||||
case ItemID.TRAILBLAZER_HARPOON_25114:
|
||||
case ItemID.CRYSTAL_HARPOON:
|
||||
case ItemID.CRYSTAL_HARPOON_23864:
|
||||
case ItemID.CRYSTAL_HARPOON_INACTIVE:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
// Reset fishing session
|
||||
if (session.getLastFishCaught() != null)
|
||||
{
|
||||
final Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
final Duration sinceCaught = Duration.between(session.getLastFishCaught(), Instant.now());
|
||||
|
||||
if (sinceCaught.compareTo(statTimeout) >= 0)
|
||||
{
|
||||
currentSpot = null;
|
||||
session.setLastFishCaught(null);
|
||||
}
|
||||
}
|
||||
|
||||
inverseSortSpotDistanceFromPlayer();
|
||||
|
||||
for (NPC npc : fishingSpots)
|
||||
{
|
||||
if (FishingSpot.findSpot(npc.getId()) == FishingSpot.MINNOW && config.showMinnowOverlay())
|
||||
{
|
||||
final int id = npc.getIndex();
|
||||
final MinnowSpot minnowSpot = minnowSpots.get(id);
|
||||
|
||||
// create the minnow spot if it doesn't already exist
|
||||
// or if it was moved, reset it
|
||||
if (minnowSpot == null
|
||||
|| !minnowSpot.getLoc().equals(npc.getWorldLocation()))
|
||||
{
|
||||
minnowSpots.put(id, new MinnowSpot(npc.getWorldLocation(), Instant.now()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.trawlerTimer())
|
||||
{
|
||||
updateTrawlerTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
final NPC npc = event.getNpc();
|
||||
|
||||
if (FishingSpot.findSpot(npc.getId()) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fishingSpots.add(npc);
|
||||
inverseSortSpotDistanceFromPlayer();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
{
|
||||
final NPC npc = npcDespawned.getNpc();
|
||||
|
||||
fishingSpots.remove(npc);
|
||||
|
||||
MinnowSpot minnowSpot = minnowSpots.remove(npc.getIndex());
|
||||
if (minnowSpot != null)
|
||||
{
|
||||
log.debug("Minnow spot {} despawned", npc);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
if (!config.trawlerNotification() || client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
|
||||
|
||||
if ((regionID == TRAWLER_SHIP_REGION_NORMAL || regionID == TRAWLER_SHIP_REGION_SINKING)
|
||||
&& client.getVar(Varbits.FISHING_TRAWLER_ACTIVITY) <= TRAWLER_ACTIVITY_THRESHOLD)
|
||||
{
|
||||
if (!trawlerNotificationSent)
|
||||
{
|
||||
notifier.notify("[" + client.getLocalPlayer().getName() + "] has low Fishing Trawler activity!");
|
||||
trawlerNotificationSent = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trawlerNotificationSent = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded event)
|
||||
{
|
||||
if (event.getGroupId() == WidgetID.FISHING_TRAWLER_GROUP_ID)
|
||||
{
|
||||
trawlerStartTime = Instant.now();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the Fishing Trawler timer widget from minutes to minutes and seconds
|
||||
*/
|
||||
private void updateTrawlerTimer()
|
||||
{
|
||||
if (trawlerStartTime == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
|
||||
if (regionID != TRAWLER_SHIP_REGION_NORMAL && regionID != TRAWLER_SHIP_REGION_SINKING)
|
||||
{
|
||||
log.debug("Trawler session ended");
|
||||
trawlerStartTime = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Widget trawlerTimerWidget = client.getWidget(WidgetInfo.FISHING_TRAWLER_TIMER);
|
||||
if (trawlerTimerWidget == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long timeLeft = TRAWLER_TIME_LIMIT_IN_SECONDS - Duration.between(trawlerStartTime, Instant.now()).getSeconds();
|
||||
if (timeLeft < 0)
|
||||
{
|
||||
timeLeft = 0;
|
||||
}
|
||||
|
||||
int minutes = (int) timeLeft / 60;
|
||||
int seconds = (int) timeLeft % 60;
|
||||
|
||||
final StringBuilder trawlerText = new StringBuilder();
|
||||
trawlerText.append("Time Left: ");
|
||||
|
||||
if (minutes > 0)
|
||||
{
|
||||
trawlerText.append(minutes);
|
||||
}
|
||||
else
|
||||
{
|
||||
trawlerText.append("00");
|
||||
}
|
||||
|
||||
trawlerText.append(':');
|
||||
|
||||
if (seconds < 10)
|
||||
{
|
||||
trawlerText.append("0");
|
||||
}
|
||||
|
||||
trawlerText.append(seconds);
|
||||
|
||||
trawlerTimerWidget.setText(trawlerText.toString());
|
||||
}
|
||||
|
||||
private void inverseSortSpotDistanceFromPlayer()
|
||||
{
|
||||
if (fishingSpots.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final LocalPoint cameraPoint = new LocalPoint(client.getCameraX(), client.getCameraY());
|
||||
fishingSpots.sort(
|
||||
Comparator.comparing(
|
||||
// Negate to have the furthest first
|
||||
(NPC npc) -> -npc.getLocalLocation().distanceTo(cameraPoint))
|
||||
// Order by position
|
||||
.thenComparing(NPC::getLocalLocation, Comparator.comparing(LocalPoint::getX)
|
||||
.thenComparing(LocalPoint::getY))
|
||||
// And then by id
|
||||
.thenComparing(NPC::getId)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.fishing;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
class FishingSession
|
||||
{
|
||||
@Getter
|
||||
@Setter
|
||||
private Instant lastFishCaught;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.fishing;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.client.game.FishingSpot;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
class FishingSpotMinimapOverlay extends Overlay
|
||||
{
|
||||
private final FishingPlugin plugin;
|
||||
private final FishingConfig config;
|
||||
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean hidden;
|
||||
|
||||
@Inject
|
||||
public FishingSpotMinimapOverlay(FishingPlugin plugin, FishingConfig config)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (hidden)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (NPC npc : plugin.getFishingSpots())
|
||||
{
|
||||
FishingSpot spot = FishingSpot.findSpot(npc.getId());
|
||||
|
||||
if (spot == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.onlyCurrentSpot() && plugin.getCurrentSpot() != null && plugin.getCurrentSpot() != spot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color color = npc.getGraphic() == GraphicID.FLYING_FISH
|
||||
? config.getMinnowsOverlayColor()
|
||||
: config.getOverlayColor();
|
||||
|
||||
net.runelite.api.Point minimapLocation = npc.getMinimapLocation();
|
||||
if (minimapLocation != null)
|
||||
{
|
||||
OverlayUtil.renderMinimapLocation(graphics, minimapLocation, color.darker());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Seth <Sethtroll3@gmail.com>
|
||||
* 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.fishing;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.game.FishingSpot;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
import net.runelite.client.ui.overlay.components.ProgressPieComponent;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
class FishingSpotOverlay extends Overlay
|
||||
{
|
||||
private static final Duration MINNOW_MOVE = Duration.ofSeconds(15);
|
||||
private static final Duration MINNOW_WARN = Duration.ofSeconds(3);
|
||||
private static final int ONE_TICK_AERIAL_FISHING = 3;
|
||||
|
||||
private final FishingPlugin plugin;
|
||||
private final FishingConfig config;
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean hidden;
|
||||
|
||||
@Inject
|
||||
private FishingSpotOverlay(FishingPlugin plugin, FishingConfig config, Client client, ItemManager itemManager)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
this.itemManager = itemManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (hidden)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
FishingSpot previousSpot = null;
|
||||
WorldPoint previousLocation = null;
|
||||
for (NPC npc : plugin.getFishingSpots())
|
||||
{
|
||||
FishingSpot spot = FishingSpot.findSpot(npc.getId());
|
||||
|
||||
if (spot == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.onlyCurrentSpot() && plugin.getCurrentSpot() != null && plugin.getCurrentSpot() != spot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// This relies on the sort order to keep identical npcs on the same tile adjacent to each other
|
||||
if (previousSpot == spot && previousLocation.equals(npc.getWorldLocation()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color color;
|
||||
if (npc.getGraphic() == GraphicID.FLYING_FISH)
|
||||
{
|
||||
color = config.getMinnowsOverlayColor();
|
||||
}
|
||||
else if (spot == FishingSpot.COMMON_TENCH && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING)
|
||||
{
|
||||
color = config.getAerialOverlayColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
color = config.getOverlayColor();
|
||||
}
|
||||
|
||||
if (spot == FishingSpot.MINNOW && config.showMinnowOverlay())
|
||||
{
|
||||
MinnowSpot minnowSpot = plugin.getMinnowSpots().get(npc.getIndex());
|
||||
if (minnowSpot != null)
|
||||
{
|
||||
long millisLeft = MINNOW_MOVE.toMillis() - Duration.between(minnowSpot.getTime(), Instant.now()).toMillis();
|
||||
if (millisLeft < MINNOW_WARN.toMillis())
|
||||
{
|
||||
color = Color.ORANGE;
|
||||
}
|
||||
|
||||
LocalPoint localPoint = npc.getLocalLocation();
|
||||
Point location = Perspective.localToCanvas(client, localPoint, client.getPlane());
|
||||
|
||||
if (location != null)
|
||||
{
|
||||
ProgressPieComponent pie = new ProgressPieComponent();
|
||||
pie.setFill(color);
|
||||
pie.setBorderColor(color);
|
||||
pie.setPosition(location);
|
||||
pie.setProgress((float) millisLeft / MINNOW_MOVE.toMillis());
|
||||
pie.render(graphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.showSpotTiles())
|
||||
{
|
||||
Polygon poly = npc.getCanvasTilePoly();
|
||||
|
||||
if (poly != null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, poly, color.darker());
|
||||
}
|
||||
}
|
||||
|
||||
if (config.showSpotIcons())
|
||||
{
|
||||
BufferedImage fishImage = itemManager.getImage(spot.getFishSpriteId());
|
||||
|
||||
if (spot == FishingSpot.COMMON_TENCH
|
||||
&& npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING)
|
||||
{
|
||||
fishImage = ImageUtil.outlineImage(itemManager.getImage(spot.getFishSpriteId()), color);
|
||||
}
|
||||
|
||||
if (fishImage != null)
|
||||
{
|
||||
Point imageLocation = npc.getCanvasImageLocation(fishImage, npc.getLogicalHeight());
|
||||
if (imageLocation != null)
|
||||
{
|
||||
OverlayUtil.renderImageLocation(graphics, imageLocation, fishImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.showSpotNames())
|
||||
{
|
||||
String text = spot.getName();
|
||||
Point textLocation = npc.getCanvasTextLocation(graphics, text, npc.getLogicalHeight() + 40);
|
||||
|
||||
if (textLocation != null)
|
||||
{
|
||||
OverlayUtil.renderTextLocation(graphics, textLocation, text, color.darker());
|
||||
}
|
||||
}
|
||||
|
||||
previousSpot = spot;
|
||||
previousLocation = npc.getWorldLocation();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.fishing;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Value
|
||||
class MinnowSpot
|
||||
{
|
||||
private final WorldPoint loc;
|
||||
private final Instant time;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Rheon <https://github.com/Rheon-D>
|
||||
* Copyright (c) 2018, 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 HOLDER 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.friendnotes;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
|
||||
class FriendNoteOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final FriendNotesPlugin plugin;
|
||||
private final TooltipManager tooltipManager;
|
||||
|
||||
@Inject
|
||||
private FriendNoteOverlay(Client client, FriendNotesPlugin plugin, TooltipManager tooltipManager)
|
||||
{
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.tooltipManager = tooltipManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (client.isMenuOpen())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add a friend note tooltip to a hovered friend list entry
|
||||
final HoveredFriend hovered = plugin.getHoveredFriend();
|
||||
|
||||
if (hovered != null) // Will always have a friend note if non-null
|
||||
{
|
||||
final String content = hovered.getNote();
|
||||
tooltipManager.add(new Tooltip(content));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ThatGamerBlue <https://github.com/ThatGamerBlue>
|
||||
* 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 HOLDER 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.friendnotes;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(FriendNotesPlugin.CONFIG_GROUP)
|
||||
public interface FriendNotesConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showIcons",
|
||||
name = "Show Icons",
|
||||
description = "Show icons on friend or ignore list",
|
||||
position = 1
|
||||
)
|
||||
default boolean showIcons()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Rheon <https://github.com/Rheon-D>
|
||||
* Copyright (c) 2018, 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 HOLDER 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.friendnotes;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Friend;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Ignore;
|
||||
import net.runelite.api.IndexedSprite;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.Nameable;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NameableNameChanged;
|
||||
import net.runelite.api.events.RemovedFriend;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Friend Notes",
|
||||
description = "Store notes about your friends"
|
||||
)
|
||||
public class FriendNotesPlugin extends Plugin
|
||||
{
|
||||
static final String CONFIG_GROUP = "friendNotes";
|
||||
private static final int CHARACTER_LIMIT = 128;
|
||||
private static final String KEY_PREFIX = "note_";
|
||||
private static final String ADD_NOTE = "Add Note";
|
||||
private static final String EDIT_NOTE = "Edit Note";
|
||||
private static final String NOTE_PROMPT_FORMAT = "%s's Notes<br>" +
|
||||
ColorUtil.prependColorTag("(Limit %s Characters)", new Color(0, 0, 170));
|
||||
private static final int ICON_WIDTH = 14;
|
||||
private static final int ICON_HEIGHT = 12;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private FriendNoteOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private FriendNotesConfig config;
|
||||
|
||||
@Getter
|
||||
private HoveredFriend hoveredFriend = null;
|
||||
|
||||
private int iconIdx = -1;
|
||||
private String currentlyLayouting;
|
||||
|
||||
@Provides
|
||||
private FriendNotesConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(FriendNotesConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
clientThread.invoke(this::loadIcon);
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
loadIcon();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!event.getGroup().equals(CONFIG_GROUP))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getKey())
|
||||
{
|
||||
case "showIcons":
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a friend note, or unset by passing a null/empty note.
|
||||
*/
|
||||
private void setFriendNote(String displayName, String note)
|
||||
{
|
||||
if (Strings.isNullOrEmpty(note))
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, KEY_PREFIX + displayName);
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager.setConfiguration(CONFIG_GROUP, KEY_PREFIX + displayName, note);
|
||||
}
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
rebuildFriendsList();
|
||||
rebuildIgnoreList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the friend note of a display name, or null if no friend note exists for it.
|
||||
*/
|
||||
@Nullable
|
||||
private String getFriendNote(String displayName)
|
||||
{
|
||||
return configManager.getConfiguration(CONFIG_GROUP, KEY_PREFIX + displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate a friend note to a new display name, and remove the previous one.
|
||||
* If current name already has a note, or previous name had none, do nothing.
|
||||
*/
|
||||
private void migrateFriendNote(String currentDisplayName, String prevDisplayName)
|
||||
{
|
||||
final String currentNote = getFriendNote(currentDisplayName);
|
||||
if (currentNote == null)
|
||||
{
|
||||
final String prevNote = getFriendNote(prevDisplayName);
|
||||
if (prevNote != null)
|
||||
{
|
||||
log.debug("Update friend's username: '{}' -> '{}'", prevDisplayName, currentDisplayName);
|
||||
setFriendNote(prevDisplayName, null);
|
||||
setFriendNote(currentDisplayName, prevNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the currently hovered display name, if a friend note exists for it.
|
||||
*/
|
||||
private void setHoveredFriend(String displayName)
|
||||
{
|
||||
hoveredFriend = null;
|
||||
|
||||
if (!Strings.isNullOrEmpty(displayName))
|
||||
{
|
||||
final String note = getFriendNote(displayName);
|
||||
if (note != null)
|
||||
{
|
||||
hoveredFriend = new HoveredFriend(displayName, note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
final int groupId = WidgetInfo.getGroupFromID(event.getActionParam1());
|
||||
|
||||
// Look for "Message" on friends list
|
||||
if ((groupId == WidgetInfo.FRIENDS_LIST.getGroupId() && event.getOption().equals("Message")) ||
|
||||
(groupId == WidgetInfo.IGNORE_LIST.getGroupId() && event.getOption().equals("Delete")))
|
||||
{
|
||||
// Friends have color tags
|
||||
setHoveredFriend(Text.toJagexName(Text.removeTags(event.getTarget())));
|
||||
|
||||
// Build "Add Note" or "Edit Note" menu entry
|
||||
final MenuEntry addNote = new MenuEntry();
|
||||
addNote.setOption(hoveredFriend == null || hoveredFriend.getNote() == null ? ADD_NOTE : EDIT_NOTE);
|
||||
addNote.setType(MenuAction.RUNELITE.getId());
|
||||
addNote.setTarget(event.getTarget()); //Preserve color codes here
|
||||
addNote.setParam0(event.getActionParam0());
|
||||
addNote.setParam1(event.getActionParam1());
|
||||
|
||||
// Add menu entry
|
||||
final MenuEntry[] menuEntries = ObjectArrays.concat(client.getMenuEntries(), addNote);
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
else if (hoveredFriend != null)
|
||||
{
|
||||
hoveredFriend = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
final int groupId = WidgetInfo.getGroupFromID(event.getWidgetId());
|
||||
|
||||
if (groupId == WidgetInfo.FRIENDS_LIST.getGroupId() || groupId == WidgetInfo.IGNORE_LIST.getGroupId())
|
||||
{
|
||||
if (Strings.isNullOrEmpty(event.getMenuTarget()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle clicks on "Add Note" or "Edit Note"
|
||||
if (event.getMenuOption().equals(ADD_NOTE) || event.getMenuOption().equals(EDIT_NOTE))
|
||||
{
|
||||
event.consume();
|
||||
|
||||
//Friends have color tags
|
||||
final String sanitizedTarget = Text.toJagexName(Text.removeTags(event.getMenuTarget()));
|
||||
final String note = getFriendNote(sanitizedTarget);
|
||||
|
||||
// Open the new chatbox input dialog
|
||||
chatboxPanelManager.openTextInput(String.format(NOTE_PROMPT_FORMAT, sanitizedTarget, CHARACTER_LIMIT))
|
||||
.value(Strings.nullToEmpty(note))
|
||||
.onDone((content) ->
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
content = Text.removeTags(content).trim();
|
||||
log.debug("Set note for '{}': '{}'", sanitizedTarget, content);
|
||||
setFriendNote(sanitizedTarget, content);
|
||||
}).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNameableNameChanged(NameableNameChanged event)
|
||||
{
|
||||
final Nameable nameable = event.getNameable();
|
||||
|
||||
if (nameable instanceof Friend || nameable instanceof Ignore)
|
||||
{
|
||||
// Migrate a friend's note to their new display name
|
||||
String name = nameable.getName();
|
||||
String prevName = nameable.getPrevName();
|
||||
|
||||
if (prevName != null)
|
||||
{
|
||||
migrateFriendNote(
|
||||
Text.toJagexName(name),
|
||||
Text.toJagexName(prevName)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onRemovedFriend(RemovedFriend event)
|
||||
{
|
||||
// Delete a friend's note if they are removed
|
||||
final String displayName = Text.toJagexName(event.getName());
|
||||
log.debug("Remove friend: '{}'", displayName);
|
||||
setFriendNote(displayName, null);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
{
|
||||
if (!config.showIcons() || iconIdx == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getEventName())
|
||||
{
|
||||
case "friend_cc_settext":
|
||||
case "ignore_cc_settext":
|
||||
String[] stringStack = client.getStringStack();
|
||||
int stringStackSize = client.getStringStackSize();
|
||||
final String rsn = stringStack[stringStackSize - 1];
|
||||
final String sanitized = Text.toJagexName(Text.removeTags(rsn));
|
||||
currentlyLayouting = sanitized;
|
||||
if (getFriendNote(sanitized) != null)
|
||||
{
|
||||
stringStack[stringStackSize - 1] = rsn + " <img=" + iconIdx + ">";
|
||||
}
|
||||
break;
|
||||
case "friend_cc_setposition":
|
||||
case "ignore_cc_setposition":
|
||||
if (currentlyLayouting == null || getFriendNote(currentlyLayouting) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int[] intStack = client.getIntStack();
|
||||
int intStackSize = client.getIntStackSize();
|
||||
int xpos = intStack[intStackSize - 4];
|
||||
xpos += ICON_WIDTH + 1;
|
||||
intStack[intStackSize - 4] = xpos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildFriendsList()
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
log.debug("Rebuilding friends list");
|
||||
client.runScript(
|
||||
ScriptID.FRIENDS_UPDATE,
|
||||
WidgetInfo.FRIEND_LIST_FULL_CONTAINER.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SORT_BY_NAME_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SORT_BY_LAST_WORLD_CHANGE_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SORT_BY_WORLD_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_LEGACY_SORT_BUTTON.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_NAMES_CONTAINER.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_SCROLL_BAR.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_LOADING_TEXT.getPackedId(),
|
||||
WidgetInfo.FRIEND_LIST_PREVIOUS_NAME_HOLDER.getPackedId()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void rebuildIgnoreList()
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
log.debug("Rebuilding ignore list");
|
||||
client.runScript(
|
||||
ScriptID.IGNORE_UPDATE,
|
||||
WidgetInfo.IGNORE_FULL_CONTAINER.getPackedId(),
|
||||
WidgetInfo.IGNORE_SORT_BY_NAME_BUTTON.getPackedId(),
|
||||
WidgetInfo.IGNORE_LEGACY_SORT_BUTTON.getPackedId(),
|
||||
WidgetInfo.IGNORE_NAMES_CONTAINER.getPackedId(),
|
||||
WidgetInfo.IGNORE_SCROLL_BAR.getPackedId(),
|
||||
WidgetInfo.IGNORE_LOADING_TEXT.getPackedId(),
|
||||
WidgetInfo.IGNORE_PREVIOUS_NAME_HOLDER.getPackedId()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void loadIcon()
|
||||
{
|
||||
final IndexedSprite[] modIcons = client.getModIcons();
|
||||
if (iconIdx != -1 || modIcons == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final BufferedImage iconImg = ImageUtil.getResourceStreamFromClass(getClass(), "note_icon.png");
|
||||
if (iconImg == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final BufferedImage resized = ImageUtil.resizeImage(iconImg, ICON_WIDTH, ICON_HEIGHT);
|
||||
|
||||
final IndexedSprite[] newIcons = Arrays.copyOf(modIcons, modIcons.length + 1);
|
||||
newIcons[newIcons.length - 1] = ImageUtil.getImageIndexedSprite(resized, client);
|
||||
|
||||
iconIdx = newIcons.length - 1;
|
||||
client.setModIcons(newIcons);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Rheon <https://github.com/Rheon-D>
|
||||
* 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 HOLDER 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.friendnotes;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
class HoveredFriend
|
||||
{
|
||||
private String friendName;
|
||||
private String note;
|
||||
}
|
||||
@@ -557,13 +557,13 @@ public class GrandExchangePlugin extends Plugin
|
||||
final MenuEntry[] entries = client.getMenuEntries();
|
||||
final MenuEntry menuEntry = entries[entries.length - 1];
|
||||
final int widgetId = menuEntry.getParam1();
|
||||
final int groupId = WidgetInfo.TO_GROUP(widgetId);
|
||||
final int groupId = WidgetInfo.getGroupFromID(widgetId);
|
||||
|
||||
switch (groupId)
|
||||
{
|
||||
case WidgetID.BANK_GROUP_ID:
|
||||
// Don't show for view tabs and such
|
||||
if (WidgetInfo.TO_CHILD(widgetId) != WidgetInfo.BANK_ITEM_CONTAINER.getChildId())
|
||||
if (WidgetInfo.getChildFromID(widgetId) != WidgetInfo.BANK_ITEM_CONTAINER.getChildId())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ public class HiscorePlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
int groupId = WidgetInfo.TO_GROUP(event.getActionParam1());
|
||||
int groupId = WidgetInfo.getGroupFromID(event.getActionParam1());
|
||||
String option = event.getOption();
|
||||
|
||||
if (groupId == WidgetInfo.FRIENDS_LIST.getGroupId() || groupId == WidgetInfo.FRIENDS_CHAT.getGroupId() ||
|
||||
|
||||
@@ -91,7 +91,7 @@ class ItemPricesOverlay extends Overlay
|
||||
final MenuEntry menuEntry = menuEntries[last];
|
||||
final MenuAction action = MenuAction.of(menuEntry.getType());
|
||||
final int widgetId = menuEntry.getParam1();
|
||||
final int groupId = WidgetInfo.TO_GROUP(widgetId);
|
||||
final int groupId = WidgetInfo.getGroupFromID(widgetId);
|
||||
final boolean isAlching = menuEntry.getOption().equals("Cast") && menuEntry.getTarget().contains("High Level Alchemy");
|
||||
|
||||
// Tooltip action type handling
|
||||
|
||||
@@ -92,8 +92,8 @@ public class ItemStatOverlay extends Overlay
|
||||
}
|
||||
|
||||
final MenuEntry entry = menu[menuSize - 1];
|
||||
final int group = WidgetInfo.TO_GROUP(entry.getParam1());
|
||||
final int child = WidgetInfo.TO_CHILD(entry.getParam1());
|
||||
final int group = WidgetInfo.getGroupFromID(entry.getParam1());
|
||||
final int child = WidgetInfo.getChildFromID(entry.getParam1());
|
||||
final Widget widget = client.getWidget(group, child);
|
||||
|
||||
if (widget == null
|
||||
|
||||
@@ -136,7 +136,7 @@ class MouseHighlightOverlay extends Overlay
|
||||
if (WIDGET_MENU_ACTIONS.contains(type))
|
||||
{
|
||||
final int widgetId = menuEntry.getParam1();
|
||||
final int groupId = WidgetInfo.TO_GROUP(widgetId);
|
||||
final int groupId = WidgetInfo.getGroupFromID(widgetId);
|
||||
|
||||
if (!config.uiTooltip())
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@ import static net.runelite.api.widgets.WidgetInfo.LIGHT_BOX_BUTTON_E;
|
||||
import static net.runelite.api.widgets.WidgetInfo.LIGHT_BOX_BUTTON_F;
|
||||
import static net.runelite.api.widgets.WidgetInfo.LIGHT_BOX_BUTTON_G;
|
||||
import static net.runelite.api.widgets.WidgetInfo.LIGHT_BOX_BUTTON_H;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
@@ -139,7 +139,7 @@ public class PuzzleSolverPlugin extends Plugin
|
||||
public void onMenuOptionClicked(MenuOptionClicked menuOptionClicked)
|
||||
{
|
||||
int widgetId = menuOptionClicked.getWidgetId();
|
||||
if (TO_GROUP(widgetId) != WidgetID.LIGHT_BOX_GROUP_ID)
|
||||
if (getGroupFromID(widgetId) != WidgetID.LIGHT_BOX_GROUP_ID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,8 +74,8 @@ class ScreenMarkerWidgetHighlightOverlay extends Overlay
|
||||
final MenuEntry menuEntry = menuEntries[menuEntries.length - 1];
|
||||
final int childIdx = menuEntry.getParam0();
|
||||
final int widgetId = menuEntry.getParam1();
|
||||
final int groupId = WidgetInfo.TO_GROUP(widgetId);
|
||||
final int componentId = WidgetInfo.TO_CHILD(widgetId);
|
||||
final int groupId = WidgetInfo.getGroupFromID(widgetId);
|
||||
final int componentId = WidgetInfo.getChildFromID(widgetId);
|
||||
|
||||
final Widget widget = client.getWidget(groupId, componentId);
|
||||
if (widget == null)
|
||||
|
||||
@@ -279,7 +279,7 @@ public class TimersPlugin extends Plugin
|
||||
{
|
||||
Widget widget = event.getWidget();
|
||||
if (WorldType.isPvpWorld(client.getWorldType())
|
||||
&& WidgetInfo.TO_GROUP(widget.getId()) == WidgetID.PVP_GROUP_ID)
|
||||
&& WidgetInfo.getGroupFromID(widget.getId()) == WidgetID.PVP_GROUP_ID)
|
||||
{
|
||||
widgetHiddenChangedOnPvpWorld = true;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
@@ -483,7 +483,7 @@ public class XpTrackerPlugin extends Plugin
|
||||
{
|
||||
int widgetID = event.getActionParam1();
|
||||
|
||||
if (TO_GROUP(widgetID) != WidgetID.SKILLS_GROUP_ID
|
||||
if (getGroupFromID(widgetID) != WidgetID.SKILLS_GROUP_ID
|
||||
|| !event.getOption().startsWith("View")
|
||||
|| !xpTrackerConfig.skillTabOverlayMenuOptions())
|
||||
{
|
||||
@@ -511,7 +511,7 @@ public class XpTrackerPlugin extends Plugin
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (event.getMenuAction().getId() != MenuAction.RUNELITE.getId()
|
||||
|| TO_GROUP(event.getWidgetId()) != WidgetID.SKILLS_GROUP_ID)
|
||||
|| getGroupFromID(event.getWidgetId()) != WidgetID.SKILLS_GROUP_ID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ import static net.runelite.api.widgets.WidgetID.PLAYER_TRADE_SCREEN_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.PLAYER_TRADE_INVENTORY_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.BANK_CONTENT_CONTAINER;
|
||||
import static net.runelite.api.widgets.WidgetInfo.BANK_TAB_CONTAINER;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import static net.runelite.api.widgets.WidgetInfo.getGroupFromID;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
|
||||
public abstract class WidgetItemOverlay extends Overlay
|
||||
@@ -80,7 +80,7 @@ public abstract class WidgetItemOverlay extends Overlay
|
||||
for (WidgetItem widgetItem : itemWidgets)
|
||||
{
|
||||
Widget widget = widgetItem.getWidget();
|
||||
int interfaceGroup = TO_GROUP(widget.getId());
|
||||
int interfaceGroup = getGroupFromID(widget.getId());
|
||||
|
||||
// Don't draw if this widget isn't one of the allowed nor in tag tab/item tab
|
||||
if (!interfaceGroups.contains(interfaceGroup) ||
|
||||
|
||||
Reference in New Issue
Block a user