Repository: runelite/runelite
Pull request #18162 (2024-08-14 17:13:12)

Replace "Only show own items" config with new "Ownership Filter" dropdown
There are three desired use cases for the ownership filtering logic.

1) Show all items

2) Show only my drops (including group iron teammates)

3) Show my drops (including group iron teammates) and world item spawns.

Before this change only use cases 1 & 2 were supported (due to [pushback](https://github.com/runelite/runelite/issues/17843#issue-2296058488) from certain vocal individuals).

This change replaces the old "Only show own items" checkbox with a dropdown that allows for all three use cases.

Note: Users that previously had the "Only show own items" checkbox enabled will **automatically** have the setting migrated to the dropdown.


Patch:
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java
index c372eae99..d736f48c8 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItem.java
@@ -75,11 +75,6 @@ class GroundItem
 		return gePrice * quantity;
 	}
 
-	boolean isMine()
-	{
-		return ownership == OWNERSHIP_SELF || ownership == OWNERSHIP_GROUP;
-	}
-
 	void reset()
 	{
 		highlighted = hidden = false;
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java
index 169350546..08f25dfa7 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java
@@ -39,11 +39,13 @@ import net.runelite.client.plugins.grounditems.config.ItemHighlightMode;
 import net.runelite.client.plugins.grounditems.config.MenuHighlightMode;
 import net.runelite.client.plugins.grounditems.config.PriceDisplayMode;
 import net.runelite.client.plugins.grounditems.config.ValueCalculationMode;
+import net.runelite.client.plugins.grounditems.config.OwnershipFilterMode;
 
 @ConfigGroup(GroundItemsConfig.GROUP)
 public interface GroundItemsConfig extends Config
 {
 	String GROUP = "grounditems";
+	String OWNERSHIP_FILTER_MODE = "ownershipFilterMode";
 
 	@ConfigSection(
 		name = "Item Lists",
@@ -362,14 +364,14 @@ public interface GroundItemsConfig extends Config
 	}
 
 	@ConfigItem(
-		keyName = "onlyShowLoot",
-		name = "Only show own items",
-		description = "Only shows items that are yours or you can pick up",
+		keyName = OWNERSHIP_FILTER_MODE,
+		name = "Ownership filter",
+		description = "Show all items, takeable items, or only your or your group's drops.",
 		position = 25
 	)
-	default boolean onlyShowOwnItems()
+	default OwnershipFilterMode ownershipFilterMode()
 	{
-		return false;
+		return OwnershipFilterMode.ALL;
 	}
 
 	@ConfigItem(
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java
index 0684df67d..c03aa0b7b 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsOverlay.java
@@ -43,11 +43,13 @@ import net.runelite.api.ItemID;
 import net.runelite.api.Perspective;
 import net.runelite.api.Player;
 import net.runelite.api.Point;
+import net.runelite.api.Varbits;
 import net.runelite.api.coords.LocalPoint;
 import net.runelite.api.coords.WorldPoint;
 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.OwnershipFilterMode;
 import net.runelite.client.plugins.grounditems.config.PriceDisplayMode;
 import net.runelite.client.ui.overlay.Overlay;
 import net.runelite.client.ui.overlay.OverlayLayer;
@@ -169,16 +171,17 @@ public class GroundItemsOverlay extends Overlay
 		plugin.setHiddenBoxBounds(null);
 		plugin.setHighlightBoxBounds(null);
 
-		final boolean onlyShowLoot = config.onlyShowOwnItems();
 		final DespawnTimerMode groundItemTimers = config.groundItemTimers();
 		final boolean outline = config.textOutline();
+		final OwnershipFilterMode ownershipFilterMode = config.ownershipFilterMode();
+		final int accountType = client.getVarbitValue(Varbits.ACCOUNT_TYPE);
 
 		for (GroundItem item : groundItemList)
 		{
 			final LocalPoint groundPoint = LocalPoint.fromWorld(client, item.getLocation());
 
 			if (groundPoint == null || localLocation.distanceTo(groundPoint) > MAX_DISTANCE
-				|| (onlyShowLoot && !item.isMine()))
+				|| !plugin.shouldDisplayItem(ownershipFilterMode, item.getOwnership(), accountType))
 			{
 				continue;
 			}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java
index ee62ad4b7..7a7c7518a 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsPlugin.java
@@ -67,6 +67,9 @@ import net.runelite.api.MenuAction;
 import net.runelite.api.MenuEntry;
 import net.runelite.api.Tile;
 import net.runelite.api.TileItem;
+import static net.runelite.api.TileItem.OWNERSHIP_GROUP;
+import static net.runelite.api.TileItem.OWNERSHIP_OTHER;
+import static net.runelite.api.TileItem.OWNERSHIP_SELF;
 import net.runelite.api.Varbits;
 import net.runelite.api.coords.WorldPoint;
 import net.runelite.api.events.ClientTick;
@@ -81,6 +84,7 @@ 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.events.ProfileChanged;
 import net.runelite.client.game.ItemManager;
 import net.runelite.client.input.KeyManager;
 import net.runelite.client.input.MouseManager;
@@ -92,6 +96,7 @@ 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;
 import static net.runelite.client.plugins.grounditems.config.MenuHighlightMode.OPTION;
+import net.runelite.client.plugins.grounditems.config.OwnershipFilterMode;
 import net.runelite.client.ui.components.colorpicker.ColorPickerManager;
 import net.runelite.client.ui.components.colorpicker.RuneliteColorPicker;
 import net.runelite.client.ui.overlay.OverlayManager;
@@ -203,6 +208,7 @@ public class GroundItemsPlugin extends Plugin
 		overlayManager.add(overlay);
 		mouseManager.registerMouseListener(mouseAdapter);
 		keyManager.registerKeyListener(hotkeyListener);
+		migrate();
 		executor.execute(this::reset);
 	}
 
@@ -231,6 +237,27 @@ public class GroundItemsPlugin extends Plugin
 		}
 	}
 
+	@Subscribe
+	public void onProfileChanged(ProfileChanged profileChanged)
+	{
+		migrate();
+	}
+
+	private void migrate()
+	{
+		//This was the old "Only show own items" config, which is now obsolete and replaced by ownership filter
+		Boolean onlyShowOwnItems = configManager.getConfiguration(GroundItemsConfig.GROUP, "onlyShowLoot", Boolean.class);
+		if (onlyShowOwnItems != null)
+		{
+			if (onlyShowOwnItems)
+			{
+				//The old behavior maps to 'Drops' in the new dropdown
+				configManager.setConfiguration(GroundItemsConfig.GROUP, GroundItemsConfig.OWNERSHIP_FILTER_MODE, OwnershipFilterMode.DROPS);
+			}
+			configManager.unsetConfiguration(GroundItemsConfig.GROUP, "onlyShowLoot");
+		}
+	}
+
 	@Subscribe
 	public void onGameStateChanged(final GameStateChanged event)
 	{
@@ -260,7 +287,7 @@ public class GroundItemsPlugin extends Plugin
 			collectedGroundItems.put(tile.getWorldLocation(), item.getId(), groundItem);
 		}
 
-		if (groundItem.isMine() || !config.onlyShowOwnItems())
+		if (shouldDisplayItem(config.ownershipFilterMode(), groundItem.getOwnership(), client.getVarbitValue(Varbits.ACCOUNT_TYPE)))
 		{
 			notifyHighlightedItem(groundItem);
 		}
@@ -389,16 +416,6 @@ public class GroundItemsPlugin extends Plugin
 		final int alchPrice = itemComposition.getHaPrice();
 		final int despawnTime = item.getDespawnTime() - client.getTickCount();
 		final int visibleTime = item.getVisibleTime() - client.getTickCount();
-		int ownership = item.getOwnership();
-		final int accountType = client.getVarbitValue(Varbits.ACCOUNT_TYPE);
-		boolean isGim = accountType >= 4 && accountType <= 6; // ~is_group_iron
-
-		// from ~script7240
-		if (ownership == TileItem.OWNERSHIP_GROUP && !isGim)
-		{
-			// non-gims see loot from other people as "group" loop since they are both group -1.
-			ownership = TileItem.OWNERSHIP_OTHER;
-		}
 
 		final GroundItem groundItem = GroundItem.builder()
 			.id(itemId)
@@ -409,7 +426,7 @@ public class GroundItemsPlugin extends Plugin
 			.haPrice(alchPrice)
 			.height(tile.getItemLayer().getHeight())
 			.tradeable(itemComposition.isTradeable())
-			.ownership(ownership)
+			.ownership(item.getOwnership())
 			.isPrivate(item.isPrivate())
 			.spawnTime(Instant.now())
 			.stackable(itemComposition.isStackable())
@@ -747,9 +764,11 @@ public class GroundItemsPlugin extends Plugin
 		int highestPrice = -1;
 		GroundItem highestItem = null;
 		Collection<GroundItem> groundItems = collectedGroundItems.row(worldPoint).values();
+		final OwnershipFilterMode ownershipFilterMode = config.ownershipFilterMode();
+		final int accountType = client.getVarbitValue(Varbits.ACCOUNT_TYPE);
 		for (GroundItem groundItem : groundItems)
 		{
-			if ((config.onlyShowOwnItems() && !groundItem.isMine()))
+			if (!shouldDisplayItem(ownershipFilterMode, groundItem.getOwnership(), accountType))
 			{
 				continue;
 			}
@@ -854,4 +873,22 @@ public class GroundItemsPlugin extends Plugin
 	{
 		configManager.unsetConfiguration(GroundItemsConfig.GROUP, HIGHLIGHT_COLOR_PREFIX + itemId);
 	}
+
+	/*
+	 * All      -> none | self | other | group
+	 * Drops    -> self | group
+	 * Takeable -> none | self | group | (if a main then other)
+	 */
+	boolean shouldDisplayItem(OwnershipFilterMode filterMode, int ownership, int accountType)
+	{
+		switch (filterMode)
+		{
+			case DROPS:
+				return ownership == OWNERSHIP_SELF || ownership == OWNERSHIP_GROUP;
+			case TAKEABLE:
+				return ownership != OWNERSHIP_OTHER || accountType == 0; // Mains can always take items
+			default:
+				return true;
+		}
+	}
 }
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/OwnershipFilterMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/OwnershipFilterMode.java
new file mode 100644
index 000000000..ccdef21c1
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/config/OwnershipFilterMode.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Moshe Ben-Zacharia <https://github.com/MosheBenZacharia>
+ * 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.config;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor
+public enum OwnershipFilterMode
+{
+	ALL("All"),
+	TAKEABLE("Takeable"),
+	DROPS("Drops");
+
+	private final String name;
+
+	@Override
+	public String toString()
+	{
+		return name;
+	}
+}


Test patch:
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java
index 1c3d2e238..7741203fc 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/grounditems/GroundItemsPluginTest.java
@@ -44,6 +44,7 @@ import net.runelite.client.game.ItemManager;
 import net.runelite.client.input.KeyManager;
 import net.runelite.client.input.MouseManager;
 import net.runelite.client.plugins.grounditems.config.HighlightTier;
+import net.runelite.client.plugins.grounditems.config.OwnershipFilterMode;
 import net.runelite.client.ui.overlay.OverlayManager;
 import org.junit.Before;
 import org.junit.Test;
@@ -124,6 +125,7 @@ public class GroundItemsPluginTest
 		when(config.getHighlightItems()).thenReturn("abyssal whip");
 		when(config.notifyTier()).thenReturn(HighlightTier.OFF);
 		when(config.notifyHighlightedDrops()).thenReturn(true);
+		when(config.ownershipFilterMode()).thenReturn(OwnershipFilterMode.ALL);
 
 		when(itemManager.getItemComposition(ItemID.ABYSSAL_WHIP)).thenAnswer(a ->
 		{