ground items plugin: add lootbeams
This commit is contained in:
@@ -204,6 +204,7 @@ public final class AnimationID
|
||||
public static final int LEAGUE_HOME_TELEPORT_4 = 8803;
|
||||
public static final int LEAGUE_HOME_TELEPORT_5 = 8805;
|
||||
public static final int LEAGUE_HOME_TELEPORT_6 = 8807;
|
||||
public static final int RAID_LIGHT_ANIMATION = 3101;
|
||||
|
||||
public static final int CONSTRUCTION = 3676;
|
||||
public static final int CONSTRUCTION_IMCANDO = 8912;
|
||||
|
||||
@@ -29,7 +29,6 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Value;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Data
|
||||
@@ -66,11 +65,4 @@ class GroundItem
|
||||
{
|
||||
return lootType != LootType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Value
|
||||
static class GroundItemKey
|
||||
{
|
||||
private int itemId;
|
||||
private WorldPoint location;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,4 +403,26 @@ public interface GroundItemsConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showLootbeamForHighlighted",
|
||||
name = "Highlighted item lootbeams",
|
||||
description = "Configures lootbeams to show for all highlighted items.",
|
||||
position = 30
|
||||
)
|
||||
default boolean showLootbeamForHighlighted()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showLootbeamTier",
|
||||
name = "Lootbeam tier",
|
||||
description = "Configures which price tiers will trigger a lootbeam",
|
||||
position = 31
|
||||
)
|
||||
default HighlightTier showLootbeamTier()
|
||||
{
|
||||
return HighlightTier.HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import net.runelite.api.coords.WorldPoint;
|
||||
import static net.runelite.client.plugins.grounditems.GroundItemsPlugin.MAX_QUANTITY;
|
||||
import net.runelite.client.plugins.grounditems.config.DespawnTimerMode;
|
||||
import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.MENU;
|
||||
import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.NONE;
|
||||
import net.runelite.client.plugins.grounditems.config.PriceDisplayMode;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
@@ -107,7 +108,8 @@ public class GroundItemsOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
final boolean dontShowOverlay = (config.itemHighlightMode() == MENU || plugin.isHideAll()) && !plugin.isHotKeyPressed();
|
||||
final boolean dontShowOverlay = (config.itemHighlightMode() == MENU || config.itemHighlightMode() == NONE
|
||||
|| plugin.isHideAll()) && !plugin.isHotKeyPressed();
|
||||
|
||||
if (dontShowOverlay && !config.highlightTiles())
|
||||
{
|
||||
|
||||
@@ -28,7 +28,9 @@ package net.runelite.client.plugins.grounditems;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.EvictingQueue;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.awt.Rectangle;
|
||||
@@ -38,7 +40,7 @@ import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
@@ -71,6 +73,7 @@ import net.runelite.api.events.ItemSpawned;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
@@ -83,7 +86,7 @@ import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.grounditems.config.HighlightTier;
|
||||
import static net.runelite.client.plugins.grounditems.config.ItemHighlightMode.OVERLAY;
|
||||
import net.runelite.client.plugins.grounditems.config.ItemHighlightMode;
|
||||
import net.runelite.client.plugins.grounditems.config.MenuHighlightMode;
|
||||
import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.BOTH;
|
||||
import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.NAME;
|
||||
@@ -158,6 +161,9 @@ public class GroundItemsPlugin extends Plugin
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@@ -177,12 +183,13 @@ public class GroundItemsPlugin extends Plugin
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
@Getter
|
||||
private final Map<GroundItem.GroundItemKey, GroundItem> collectedGroundItems = new LinkedHashMap<>();
|
||||
private final Table<WorldPoint, Integer, GroundItem> collectedGroundItems = HashBasedTable.create();
|
||||
private List<PriceHighlight> priceChecks = ImmutableList.of();
|
||||
private LoadingCache<NamedQuantity, Boolean> highlightedItems;
|
||||
private LoadingCache<NamedQuantity, Boolean> hiddenItems;
|
||||
private final Queue<Integer> droppedItemQueue = EvictingQueue.create(16); // recently dropped items
|
||||
private int lastUsedItem;
|
||||
private final Map<WorldPoint, Lootbeam> lootbeams = new HashMap<>();
|
||||
|
||||
@Provides
|
||||
GroundItemsConfig provideConfig(ConfigManager configManager)
|
||||
@@ -213,6 +220,7 @@ public class GroundItemsPlugin extends Plugin
|
||||
hiddenItemList = null;
|
||||
highlightedItemsList = null;
|
||||
collectedGroundItems.clear();
|
||||
clientThread.invokeLater(this::removeAllLootbeams);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -230,6 +238,7 @@ public class GroundItemsPlugin extends Plugin
|
||||
if (event.getGameState() == GameState.LOADING)
|
||||
{
|
||||
collectedGroundItems.clear();
|
||||
lootbeams.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,19 +249,23 @@ public class GroundItemsPlugin extends Plugin
|
||||
Tile tile = itemSpawned.getTile();
|
||||
|
||||
GroundItem groundItem = buildGroundItem(tile, item);
|
||||
|
||||
GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation());
|
||||
GroundItem existing = collectedGroundItems.putIfAbsent(groundItemKey, groundItem);
|
||||
GroundItem existing = collectedGroundItems.get(tile.getWorldLocation(), item.getId());
|
||||
if (existing != null)
|
||||
{
|
||||
existing.setQuantity(existing.getQuantity() + groundItem.getQuantity());
|
||||
// The spawn time remains set at the oldest spawn
|
||||
}
|
||||
else
|
||||
{
|
||||
collectedGroundItems.put(tile.getWorldLocation(), item.getId(), groundItem);
|
||||
}
|
||||
|
||||
if (!config.onlyShowLoot())
|
||||
{
|
||||
notifyHighlightedItem(groundItem);
|
||||
}
|
||||
|
||||
handleLootbeam(tile.getWorldLocation());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -261,8 +274,7 @@ public class GroundItemsPlugin extends Plugin
|
||||
TileItem item = itemDespawned.getItem();
|
||||
Tile tile = itemDespawned.getTile();
|
||||
|
||||
GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation());
|
||||
GroundItem groundItem = collectedGroundItems.get(groundItemKey);
|
||||
GroundItem groundItem = collectedGroundItems.get(tile.getWorldLocation(), item.getId());
|
||||
if (groundItem == null)
|
||||
{
|
||||
return;
|
||||
@@ -270,7 +282,7 @@ public class GroundItemsPlugin extends Plugin
|
||||
|
||||
if (groundItem.getQuantity() <= item.getQuantity())
|
||||
{
|
||||
collectedGroundItems.remove(groundItemKey);
|
||||
collectedGroundItems.remove(tile.getWorldLocation(), item.getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -280,6 +292,8 @@ public class GroundItemsPlugin extends Plugin
|
||||
// time
|
||||
groundItem.setSpawnTime(null);
|
||||
}
|
||||
|
||||
handleLootbeam(tile.getWorldLocation());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -291,12 +305,13 @@ public class GroundItemsPlugin extends Plugin
|
||||
int newQuantity = itemQuantityChanged.getNewQuantity();
|
||||
|
||||
int diff = newQuantity - oldQuantity;
|
||||
GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(item.getId(), tile.getWorldLocation());
|
||||
GroundItem groundItem = collectedGroundItems.get(groundItemKey);
|
||||
GroundItem groundItem = collectedGroundItems.get(tile.getWorldLocation(), item.getId());
|
||||
if (groundItem != null)
|
||||
{
|
||||
groundItem.setQuantity(groundItem.getQuantity() + diff);
|
||||
}
|
||||
|
||||
handleLootbeam(tile.getWorldLocation());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -366,8 +381,7 @@ public class GroundItemsPlugin extends Plugin
|
||||
for (ItemStack itemStack : items)
|
||||
{
|
||||
WorldPoint location = WorldPoint.fromLocal(client, itemStack.getLocation());
|
||||
GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(itemStack.getId(), location);
|
||||
GroundItem groundItem = collectedGroundItems.get(groundItemKey);
|
||||
GroundItem groundItem = collectedGroundItems.get(location, itemStack.getId());
|
||||
if (groundItem != null)
|
||||
{
|
||||
groundItem.setLootType(lootType);
|
||||
@@ -460,12 +474,14 @@ public class GroundItemsPlugin extends Plugin
|
||||
}
|
||||
|
||||
priceChecks = priceCheckBuilder.build();
|
||||
|
||||
clientThread.invokeLater(this::handleLootbeams);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (config.itemHighlightMode() != OVERLAY)
|
||||
if (config.itemHighlightMode() == ItemHighlightMode.MENU || config.itemHighlightMode() == ItemHighlightMode.BOTH)
|
||||
{
|
||||
final boolean telegrabEntry = event.getOption().equals("Cast") && event.getTarget().startsWith(TELEGRAB_TEXT) && event.getType() == CAST_ON_ITEM;
|
||||
if (!(event.getOption().equals("Take") && event.getType() == THIRD_OPTION) && !telegrabEntry)
|
||||
@@ -481,8 +497,7 @@ public class GroundItemsPlugin extends Plugin
|
||||
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
|
||||
|
||||
final WorldPoint worldPoint = WorldPoint.fromScene(client, sceneX, sceneY, client.getPlane());
|
||||
GroundItem.GroundItemKey groundItemKey = new GroundItem.GroundItemKey(itemId, worldPoint);
|
||||
GroundItem groundItem = collectedGroundItems.get(groundItemKey);
|
||||
GroundItem groundItem = collectedGroundItems.get(worldPoint, itemId);
|
||||
int quantity = groundItem.getQuantity();
|
||||
|
||||
final int gePrice = groundItem.getGePrice();
|
||||
@@ -705,4 +720,103 @@ public class GroundItemsPlugin extends Plugin
|
||||
lastUsedItem = clickedItem.getId();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLootbeam(WorldPoint worldPoint)
|
||||
{
|
||||
/*
|
||||
* Return and remove the lootbeam from this location if lootbeam are disabled
|
||||
* Lootbeam can be at this location if the config was just changed
|
||||
*/
|
||||
if (!(config.showLootbeamForHighlighted() || config.showLootbeamTier() != HighlightTier.OFF))
|
||||
{
|
||||
removeLootbeam(worldPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
int price = -1;
|
||||
Collection<GroundItem> groundItems = collectedGroundItems.row(worldPoint).values();
|
||||
for (GroundItem groundItem : groundItems)
|
||||
{
|
||||
if ((config.onlyShowLoot() && !groundItem.isMine()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* highlighted items have the highest priority so if an item is highlighted at this location
|
||||
* we can early return
|
||||
*/
|
||||
NamedQuantity item = new NamedQuantity(groundItem);
|
||||
if (config.showLootbeamForHighlighted()
|
||||
&& TRUE.equals(highlightedItems.getUnchecked(item)))
|
||||
{
|
||||
addLootbeam(worldPoint, config.highlightedColor());
|
||||
return;
|
||||
}
|
||||
|
||||
// Explicit hide takes priority over implicit highlight
|
||||
if (TRUE.equals(hiddenItems.getUnchecked(item)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int itemPrice = getValueByMode(groundItem.getGePrice(), groundItem.getHaPrice());
|
||||
price = Math.max(itemPrice, price);
|
||||
}
|
||||
|
||||
if (config.showLootbeamTier() != HighlightTier.OFF)
|
||||
{
|
||||
for (PriceHighlight highlight : priceChecks)
|
||||
{
|
||||
if (price > highlight.getPrice() && price > config.showLootbeamTier().getValueFromTier(config))
|
||||
{
|
||||
addLootbeam(worldPoint, highlight.color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeLootbeam(worldPoint);
|
||||
}
|
||||
|
||||
private void handleLootbeams()
|
||||
{
|
||||
for (WorldPoint worldPoint : collectedGroundItems.rowKeySet())
|
||||
{
|
||||
handleLootbeam(worldPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeAllLootbeams()
|
||||
{
|
||||
for (Lootbeam lootbeam : lootbeams.values())
|
||||
{
|
||||
lootbeam.remove();
|
||||
}
|
||||
|
||||
lootbeams.clear();
|
||||
}
|
||||
|
||||
private void addLootbeam(WorldPoint worldPoint, Color color)
|
||||
{
|
||||
Lootbeam lootbeam = lootbeams.get(worldPoint);
|
||||
if (lootbeam == null)
|
||||
{
|
||||
lootbeam = new Lootbeam(client, worldPoint, color);
|
||||
lootbeams.put(worldPoint, lootbeam);
|
||||
}
|
||||
else
|
||||
{
|
||||
lootbeam.setColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLootbeam(WorldPoint worldPoint)
|
||||
{
|
||||
Lootbeam lootbeam = lootbeams.remove(worldPoint);
|
||||
if (lootbeam != null)
|
||||
{
|
||||
lootbeam.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Trevor <https://github.com/Trevor159>
|
||||
* 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.grounditems;
|
||||
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.JagexColor;
|
||||
import net.runelite.api.RuneLiteObject;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import java.awt.Color;
|
||||
|
||||
class Lootbeam
|
||||
{
|
||||
private static final int RAID_LIGHT_MODEL = 5809;
|
||||
private static final short RAID_LIGHT_FIND_COLOR = 6371;
|
||||
|
||||
private final RuneLiteObject runeLiteObject;
|
||||
private final Client client;
|
||||
private Color color;
|
||||
|
||||
public Lootbeam(Client client, WorldPoint worldPoint, Color color)
|
||||
{
|
||||
this.client = client;
|
||||
runeLiteObject = client.createRuneLiteObject();
|
||||
|
||||
setColor(color);
|
||||
runeLiteObject.setAnimation(client.loadAnimation(AnimationID.RAID_LIGHT_ANIMATION));
|
||||
runeLiteObject.setShouldLoop(true);
|
||||
|
||||
LocalPoint lp = LocalPoint.fromWorld(client, worldPoint);
|
||||
runeLiteObject.setLocation(lp, client.getPlane());
|
||||
|
||||
runeLiteObject.setActive(true);
|
||||
}
|
||||
|
||||
public void setColor(Color color)
|
||||
{
|
||||
if (this.color != null && this.color.equals(color))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.color = color;
|
||||
runeLiteObject.setModel(client.loadModel(
|
||||
RAID_LIGHT_MODEL,
|
||||
new short[]{RAID_LIGHT_FIND_COLOR},
|
||||
new short[]{JagexColor.rgbToHSL(color.getRGB(), 1.0d)}
|
||||
));
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
runeLiteObject.setActive(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import lombok.RequiredArgsConstructor;
|
||||
@RequiredArgsConstructor
|
||||
public enum ItemHighlightMode
|
||||
{
|
||||
NONE("None"),
|
||||
OVERLAY("Overlay"),
|
||||
MENU("Right-click menu"),
|
||||
BOTH("Both");
|
||||
|
||||
@@ -111,6 +111,8 @@ public class GroundItemsPluginTest
|
||||
|
||||
when(client.getLocalPlayer()).thenReturn(mock(Player.class));
|
||||
when(config.getHiddenItems()).thenReturn("");
|
||||
when(config.showLootbeamForHighlighted()).thenReturn(false);
|
||||
when(config.showLootbeamTier()).thenReturn(HighlightTier.OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user