menuentryswapper: various changes and fixes. (#1368)
* menuentryswapper: various changes and fixes. * menuentryswapper: fix "rub" and "teleport" on inventory items. * menuentryswapper: fix "reset" on box traps * menuentryswapper: fix use bones.
This commit is contained in:
@@ -50,10 +50,11 @@ public class MenuOptionClicked implements Event
|
|||||||
authentic = true;
|
authentic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MenuOptionClicked(MenuEntry entry, boolean authentic)
|
public MenuOptionClicked(MenuEntry entry, boolean authentic, int mouseButton)
|
||||||
{
|
{
|
||||||
menuEntry = entry;
|
menuEntry = entry;
|
||||||
this.authentic = authentic;
|
this.authentic = authentic;
|
||||||
|
this.mouseButton = mouseButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,6 +128,11 @@ public class MenuOptionClicked implements Event
|
|||||||
*/
|
*/
|
||||||
private boolean consumed;
|
private boolean consumed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mouse button will be 1 if a non draggable widget was clicked,
|
||||||
|
*/
|
||||||
|
private int mouseButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the event as having been consumed.
|
* Marks the event as having been consumed.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -71,6 +71,6 @@ public interface ComparableEntries
|
|||||||
*/
|
*/
|
||||||
static BankComparableEntry newBankComparableEntry(String option, String itemName)
|
static BankComparableEntry newBankComparableEntry(String option, String itemName)
|
||||||
{
|
{
|
||||||
return new BankComparableEntry(option, itemName);
|
return new BankComparableEntry(option, itemName, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,9 +429,7 @@ public class MenuManager
|
|||||||
{
|
{
|
||||||
if (!client.isMenuOpen() && event.isAuthentic())
|
if (!client.isMenuOpen() && event.isAuthentic())
|
||||||
{
|
{
|
||||||
// The mouse button will not be 0 if a non draggable widget was clicked,
|
if (event.getMouseButton() != 0)
|
||||||
// otherwise the left click entry will have been set in onWidgetPressed
|
|
||||||
if (client.getMouseCurrentButton() != 0)
|
|
||||||
{
|
{
|
||||||
leftClickEntry = rebuildLeftClickMenu();
|
leftClickEntry = rebuildLeftClickMenu();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ import net.runelite.client.util.Text;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class BankComparableEntry extends AbstractComparableEntry
|
public class BankComparableEntry extends AbstractComparableEntry
|
||||||
{
|
{
|
||||||
public BankComparableEntry(String option, String itemName)
|
public BankComparableEntry(String option, String itemName, boolean strictTarget)
|
||||||
{
|
{
|
||||||
this.setOption(Text.standardize(option));
|
this.setOption(Text.standardize(option));
|
||||||
this.setTarget(Text.standardize(itemName));
|
this.setTarget(Text.standardize(itemName));
|
||||||
|
this.setStrictTarget(strictTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean matches(MenuEntry entry)
|
public boolean matches(MenuEntry entry)
|
||||||
@@ -25,6 +26,11 @@ public class BankComparableEntry extends AbstractComparableEntry
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Text.standardize(entry.getOption()).contains(this.getOption()) && Text.standardize(entry.getTarget()).equals(this.getTarget());
|
if (isStrictTarget() && Text.standardize(entry.getTarget()).equals(this.getTarget()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Text.standardize(entry.getOption()).contains(this.getOption()) && Text.standardize(entry.getTarget()).contains(this.getTarget());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package net.runelite.client.plugins.menuentryswapper;
|
||||||
|
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import net.runelite.api.MenuEntry;
|
||||||
|
import net.runelite.api.widgets.WidgetID;
|
||||||
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.client.menus.AbstractComparableEntry;
|
||||||
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class InventoryComparableEntry extends AbstractComparableEntry
|
||||||
|
{
|
||||||
|
public InventoryComparableEntry(String option, String itemName, boolean strictTarget)
|
||||||
|
{
|
||||||
|
this.setOption(Text.standardize(option));
|
||||||
|
this.setTarget(Text.standardize(itemName));
|
||||||
|
this.setStrictTarget(strictTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(MenuEntry entry)
|
||||||
|
{
|
||||||
|
final int groupId = WidgetInfo.TO_GROUP(entry.getParam1());
|
||||||
|
|
||||||
|
if (groupId != WidgetID.INVENTORY_GROUP_ID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStrictTarget() && Text.standardize(entry.getTarget()).equals(this.getTarget()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Text.standardize(entry.getOption()).contains(this.getOption()) && Text.standardize(entry.getTarget()).contains(this.getTarget());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1248,7 +1248,7 @@ public class MenuEntrySwapperPlugin extends Plugin
|
|||||||
|
|
||||||
if (this.swapBoxTrap)
|
if (this.swapBoxTrap)
|
||||||
{
|
{
|
||||||
menuManager.addPriorityEntry("Reset", "Box trap");
|
menuManager.addPriorityEntry("Reset", "Shaking box");
|
||||||
menuManager.addPriorityEntry("Lay", "Box trap");
|
menuManager.addPriorityEntry("Lay", "Box trap");
|
||||||
menuManager.addPriorityEntry("Activate", "Box trap");
|
menuManager.addPriorityEntry("Activate", "Box trap");
|
||||||
}
|
}
|
||||||
@@ -1318,21 +1318,19 @@ public class MenuEntrySwapperPlugin extends Plugin
|
|||||||
|
|
||||||
if (this.swapTeleportItem)
|
if (this.swapTeleportItem)
|
||||||
{
|
{
|
||||||
menuManager.addSwap("Wear", "", "Rub");
|
menuManager.addPriorityEntry(new InventoryComparableEntry("Rub", "", false)).setPriority(1);
|
||||||
menuManager.addSwap("Wield", "", "Rub");
|
menuManager.addPriorityEntry(new InventoryComparableEntry("Teleport", "", false)).setPriority(1);
|
||||||
menuManager.addSwap("Wear", "", "Teleport");
|
|
||||||
menuManager.addSwap("Wield", "", "Teleport");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.swapCoalBag)
|
if (this.swapCoalBag)
|
||||||
{
|
{
|
||||||
menuManager.addPriorityEntry("Fill", "Coal bag");
|
menuManager.addPriorityEntry("Fill", "Coal bag");
|
||||||
menuManager.addPriorityEntry(new BankComparableEntry("Empty", "Coal bag"));
|
menuManager.addPriorityEntry(newBankComparableEntry("Empty", "Coal bag"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.swapBones)
|
if (this.swapBones)
|
||||||
{
|
{
|
||||||
menuManager.addSwap("Bury", "", "Use");
|
menuManager.addPriorityEntry(new InventoryComparableEntry("Use", "bone", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.swapNexus)
|
if (this.swapNexus)
|
||||||
@@ -1498,17 +1496,20 @@ public class MenuEntrySwapperPlugin extends Plugin
|
|||||||
Text.fromCSV(this.getSellFiftyItems).forEach(item -> menuManager.removePriorityEntry("Sell 50", item));
|
Text.fromCSV(this.getSellFiftyItems).forEach(item -> menuManager.removePriorityEntry("Sell 50", item));
|
||||||
menuManager.removeSwaps("Fairy ring");
|
menuManager.removeSwaps("Fairy ring");
|
||||||
menuManager.removeSwaps("Tree");
|
menuManager.removeSwaps("Tree");
|
||||||
menuManager.removePriorityEntry(this.getGloryMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getBurningAmuletMode.toString(), "burning amulet"));
|
||||||
menuManager.removePriorityEntry(this.getGloryMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getCombatBraceletMode.toString(), "combat bracelet"));
|
||||||
menuManager.removePriorityEntry(this.getSkillsNecklaceMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getGamesNecklaceMode.toString(), "games necklace"));
|
||||||
menuManager.removePriorityEntry(this.getNecklaceofPassageMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getDuelingRingMode.toString(), "ring of dueling"));
|
||||||
menuManager.removePriorityEntry(this.getDigsitePendantMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getGloryMode.toString(), "glory"));
|
||||||
menuManager.removePriorityEntry(this.getSlayerRingMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getSkillsNecklaceMode.toString(), "skills necklace"));
|
||||||
menuManager.removePriorityEntry(this.getSlayerRingMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getNecklaceofPassageMode.toString(), "necklace of passage"));
|
||||||
menuManager.removePriorityEntry(this.getXericsTalismanMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getDigsitePendantMode.toString(), "digsite pendant"));
|
||||||
menuManager.removePriorityEntry(this.getRingofWealthMode.toString());
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getSlayerRingMode.toString(), "slayer ring"));
|
||||||
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getXericsTalismanMode.toString(), "talisman"));
|
||||||
|
menuManager.removePriorityEntry(new EquipmentComparableEntry(this.getRingofWealthMode.toString(), "ring of wealth"));
|
||||||
menuManager.removePriorityEntry(this.maxMode.toString(), "max cape");
|
menuManager.removePriorityEntry(this.maxMode.toString(), "max cape");
|
||||||
menuManager.removePriorityEntry(this.questCapeMode.toString(), "quest point cape");
|
menuManager.removePriorityEntry(this.questCapeMode.toString(), "quest point cape");
|
||||||
|
menuManager.removePriorityEntry(new InventoryComparableEntry("Use", "bone", false));
|
||||||
menuManager.removePriorityEntry("Smith All");
|
menuManager.removePriorityEntry("Smith All");
|
||||||
menuManager.removePriorityEntry("Smith All Sets");
|
menuManager.removePriorityEntry("Smith All Sets");
|
||||||
menuManager.removePriorityEntry("Tan All");
|
menuManager.removePriorityEntry("Tan All");
|
||||||
@@ -1568,7 +1569,7 @@ public class MenuEntrySwapperPlugin extends Plugin
|
|||||||
menuManager.removePriorityEntry("Pay-toll(10gp)", "Gate");
|
menuManager.removePriorityEntry("Pay-toll(10gp)", "Gate");
|
||||||
menuManager.removePriorityEntry("Travel", "Trapdoor");
|
menuManager.removePriorityEntry("Travel", "Trapdoor");
|
||||||
menuManager.removePriorityEntry("Harpoon");
|
menuManager.removePriorityEntry("Harpoon");
|
||||||
menuManager.removePriorityEntry("Reset", "Box trap");
|
menuManager.removePriorityEntry("Reset", "Shaking box");
|
||||||
menuManager.removePriorityEntry("Lay", "Box trap");
|
menuManager.removePriorityEntry("Lay", "Box trap");
|
||||||
menuManager.removePriorityEntry("Activate", "Box trap");
|
menuManager.removePriorityEntry("Activate", "Box trap");
|
||||||
menuManager.removePriorityEntry("Chase");
|
menuManager.removePriorityEntry("Chase");
|
||||||
@@ -1601,10 +1602,8 @@ public class MenuEntrySwapperPlugin extends Plugin
|
|||||||
menuManager.removePriorityEntry("Search");
|
menuManager.removePriorityEntry("Search");
|
||||||
menuManager.removePriorityEntry("Search for traps");
|
menuManager.removePriorityEntry("Search for traps");
|
||||||
menuManager.removePriorityEntry("Guzzle", "Dwarven rock cake");
|
menuManager.removePriorityEntry("Guzzle", "Dwarven rock cake");
|
||||||
menuManager.removeSwap("Wear", "", "Rub");
|
menuManager.removePriorityEntry(new InventoryComparableEntry("Rub", "", false));
|
||||||
menuManager.removeSwap("Wield", "", "Rub");
|
menuManager.removePriorityEntry(new InventoryComparableEntry("Teleport", "", false));
|
||||||
menuManager.removeSwap("Wear", "", "Teleport");
|
|
||||||
menuManager.removeSwap("Wield", "", "Teleport");
|
|
||||||
menuManager.removePriorityEntry(this.getConstructionMode.getBuild());
|
menuManager.removePriorityEntry(this.getConstructionMode.getBuild());
|
||||||
menuManager.removePriorityEntry(this.getConstructionMode.getRemove());
|
menuManager.removePriorityEntry(this.getConstructionMode.getRemove());
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ public interface RunecraftConfig extends Config
|
|||||||
name = "Lavas",
|
name = "Lavas",
|
||||||
description = "Swaps Ring of dueling menu entry depending on location, requires fire tiara or RC cape to be worn.",
|
description = "Swaps Ring of dueling menu entry depending on location, requires fire tiara or RC cape to be worn.",
|
||||||
parent = "utilStub",
|
parent = "utilStub",
|
||||||
|
warning = "<html><center>This config option is incompatible with menu-entry-swapper equipment swaps." +
|
||||||
|
"<br>Expect bugs if you use them together.</html></center>",
|
||||||
position = 2
|
position = 2
|
||||||
)
|
)
|
||||||
default boolean Lavas()
|
default boolean Lavas()
|
||||||
|
|||||||
@@ -24,10 +24,9 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.runecraft;
|
package net.runelite.client.plugins.runecraft;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -37,12 +36,11 @@ import lombok.Getter;
|
|||||||
import net.runelite.api.ChatMessageType;
|
import net.runelite.api.ChatMessageType;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.DecorativeObject;
|
import net.runelite.api.DecorativeObject;
|
||||||
import net.runelite.api.EquipmentInventorySlot;
|
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.InventoryID;
|
import net.runelite.api.InventoryID;
|
||||||
import net.runelite.api.Item;
|
import net.runelite.api.Item;
|
||||||
|
import net.runelite.api.ItemContainer;
|
||||||
import net.runelite.api.ItemID;
|
import net.runelite.api.ItemID;
|
||||||
import net.runelite.api.MenuEntry;
|
|
||||||
import net.runelite.api.NPC;
|
import net.runelite.api.NPC;
|
||||||
import net.runelite.api.NpcID;
|
import net.runelite.api.NpcID;
|
||||||
import net.runelite.api.events.ChatMessage;
|
import net.runelite.api.events.ChatMessage;
|
||||||
@@ -51,18 +49,19 @@ import net.runelite.api.events.DecorativeObjectDespawned;
|
|||||||
import net.runelite.api.events.DecorativeObjectSpawned;
|
import net.runelite.api.events.DecorativeObjectSpawned;
|
||||||
import net.runelite.api.events.GameStateChanged;
|
import net.runelite.api.events.GameStateChanged;
|
||||||
import net.runelite.api.events.ItemContainerChanged;
|
import net.runelite.api.events.ItemContainerChanged;
|
||||||
import net.runelite.api.events.MenuEntryAdded;
|
|
||||||
import net.runelite.api.events.NpcDespawned;
|
import net.runelite.api.events.NpcDespawned;
|
||||||
import net.runelite.api.events.NpcSpawned;
|
import net.runelite.api.events.NpcSpawned;
|
||||||
import net.runelite.client.Notifier;
|
import net.runelite.client.Notifier;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.EventBus;
|
import net.runelite.client.eventbus.EventBus;
|
||||||
|
import net.runelite.client.menus.BaseComparableEntry;
|
||||||
|
import static net.runelite.client.menus.ComparableEntries.newBaseComparableEntry;
|
||||||
import net.runelite.client.menus.MenuManager;
|
import net.runelite.client.menus.MenuManager;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
|
import net.runelite.client.plugins.menuentryswapper.BankComparableEntry;
|
||||||
|
import net.runelite.client.plugins.menuentryswapper.EquipmentComparableEntry;
|
||||||
import net.runelite.client.ui.overlay.OverlayManager;
|
import net.runelite.client.ui.overlay.OverlayManager;
|
||||||
import static net.runelite.client.util.MenuUtil.swap;
|
|
||||||
import net.runelite.client.util.Text;
|
|
||||||
|
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
@@ -71,89 +70,68 @@ import net.runelite.client.util.Text;
|
|||||||
tags = {"abyssal", "minimap", "overlay", "rifts", "rc", "runecrafting"}
|
tags = {"abyssal", "minimap", "overlay", "rifts", "rc", "runecrafting"}
|
||||||
)
|
)
|
||||||
@Singleton
|
@Singleton
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
public class RunecraftPlugin extends Plugin
|
public class RunecraftPlugin extends Plugin
|
||||||
{
|
{
|
||||||
private static final int FIRE_ALTAR = 10315;
|
private static final BankComparableEntry POUCH = new BankComparableEntry("fill", "pouch", false);
|
||||||
private static final String POUCH_DECAYED_NOTIFICATION_MESSAGE = "Your rune pouch has decayed.";
|
private static final BaseComparableEntry EMPTY = newBaseComparableEntry("empty", "pouch", false);
|
||||||
|
private static final EquipmentComparableEntry CASTLE_WARS = new EquipmentComparableEntry("castle wars", "ring of dueling");
|
||||||
|
private static final EquipmentComparableEntry DUEL_ARENA = new EquipmentComparableEntry("duel arena", "ring of dueling");
|
||||||
private static final String POUCH_DECAYED_MESSAGE = "Your pouch has decayed through use.";
|
private static final String POUCH_DECAYED_MESSAGE = "Your pouch has decayed through use.";
|
||||||
private static final List<Integer> DEGRADED_POUCHES = ImmutableList.of(
|
private static final String POUCH_DECAYED_NOTIFICATION_MESSAGE = "Your rune pouch has decayed.";
|
||||||
|
private static final int FIRE_ALTAR = 10315;
|
||||||
|
private static final Set<Integer> DEGRADED_POUCHES = ImmutableSet.of(
|
||||||
ItemID.MEDIUM_POUCH_5511,
|
ItemID.MEDIUM_POUCH_5511,
|
||||||
ItemID.LARGE_POUCH_5513,
|
ItemID.LARGE_POUCH_5513,
|
||||||
ItemID.GIANT_POUCH_5515
|
ItemID.GIANT_POUCH_5515
|
||||||
);
|
);
|
||||||
|
|
||||||
private boolean wearingTiara;
|
|
||||||
private boolean wearingCape;
|
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private final Set<DecorativeObject> abyssObjects = new HashSet<>();
|
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean degradedPouchInInventory;
|
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private NPC darkMage;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private OverlayManager overlayManager;
|
private OverlayManager overlayManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private AbyssOverlay abyssOverlay;
|
private AbyssOverlay abyssOverlay;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private RunecraftOverlay runecraftOverlay;
|
private RunecraftOverlay runecraftOverlay;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private RunecraftConfig config;
|
private RunecraftConfig config;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private Notifier notifier;
|
private Notifier notifier;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private MenuManager menuManager;
|
private MenuManager menuManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
private EventBus eventBus;
|
private EventBus eventBus;
|
||||||
|
|
||||||
private boolean Lavas;
|
private final Set<DecorativeObject> abyssObjects = new HashSet<>();
|
||||||
@Getter(AccessLevel.PACKAGE)
|
private boolean degradedPouchInInventory;
|
||||||
private boolean essPouch;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean hightlightDarkMage;
|
|
||||||
private boolean degradingNotification;
|
private boolean degradingNotification;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
private boolean essPouch;
|
||||||
private boolean showRifts;
|
private boolean hightlightDarkMage;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
private boolean lavas;
|
||||||
private boolean showAir;
|
private boolean showAir;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showBlood;
|
private boolean showBlood;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showBody;
|
private boolean showBody;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showChaos;
|
private boolean showChaos;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showCosmic;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showDeath;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showEarth;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showFire;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showLaw;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showMind;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showNature;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showSoul;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showWater;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private boolean showClickBox;
|
private boolean showClickBox;
|
||||||
|
private boolean showCosmic;
|
||||||
|
private boolean showDeath;
|
||||||
|
private boolean showEarth;
|
||||||
|
private boolean showFire;
|
||||||
|
private boolean showLaw;
|
||||||
|
private boolean showMind;
|
||||||
|
private boolean showNature;
|
||||||
|
private boolean showRifts;
|
||||||
|
private boolean showSoul;
|
||||||
|
private boolean showWater;
|
||||||
|
private NPC darkMage;
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
RunecraftConfig getConfig(ConfigManager configManager)
|
RunecraftConfig getConfig(ConfigManager configManager)
|
||||||
@@ -166,22 +144,20 @@ public class RunecraftPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
updateConfig();
|
updateConfig();
|
||||||
addSubscriptions();
|
addSubscriptions();
|
||||||
|
|
||||||
overlayManager.add(abyssOverlay);
|
|
||||||
abyssOverlay.updateConfig();
|
abyssOverlay.updateConfig();
|
||||||
|
overlayManager.add(abyssOverlay);
|
||||||
overlayManager.add(runecraftOverlay);
|
overlayManager.add(runecraftOverlay);
|
||||||
addSwaps();
|
handleSwaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void shutDown() throws Exception
|
protected void shutDown() throws Exception
|
||||||
{
|
{
|
||||||
eventBus.unregister(this);
|
eventBus.unregister(this);
|
||||||
|
|
||||||
overlayManager.remove(abyssOverlay);
|
|
||||||
abyssObjects.clear();
|
abyssObjects.clear();
|
||||||
darkMage = null;
|
darkMage = null;
|
||||||
degradedPouchInInventory = false;
|
degradedPouchInInventory = false;
|
||||||
|
overlayManager.remove(abyssOverlay);
|
||||||
overlayManager.remove(runecraftOverlay);
|
overlayManager.remove(runecraftOverlay);
|
||||||
removeSwaps();
|
removeSwaps();
|
||||||
}
|
}
|
||||||
@@ -190,7 +166,6 @@ public class RunecraftPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||||
eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
|
eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
|
||||||
eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded);
|
|
||||||
eventBus.subscribe(DecorativeObjectSpawned.class, this, this::onDecorativeObjectSpawned);
|
eventBus.subscribe(DecorativeObjectSpawned.class, this, this::onDecorativeObjectSpawned);
|
||||||
eventBus.subscribe(DecorativeObjectDespawned.class, this, this::onDecorativeObjectDespawned);
|
eventBus.subscribe(DecorativeObjectDespawned.class, this, this::onDecorativeObjectDespawned);
|
||||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||||
@@ -208,9 +183,10 @@ public class RunecraftPlugin extends Plugin
|
|||||||
|
|
||||||
updateConfig();
|
updateConfig();
|
||||||
|
|
||||||
if (event.getKey().equals("essPouch"))
|
if (event.getKey().equals("essPouch") || event.getKey().equals("Lavas"))
|
||||||
{
|
{
|
||||||
addSwaps();
|
removeSwaps();
|
||||||
|
handleSwaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
abyssOverlay.updateConfig();
|
abyssOverlay.updateConfig();
|
||||||
@@ -229,83 +205,9 @@ public class RunecraftPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onMenuEntryAdded(MenuEntryAdded entry)
|
|
||||||
{
|
|
||||||
if (wearingCape || wearingTiara)
|
|
||||||
{
|
|
||||||
final String option = Text.removeTags(entry.getOption()).toLowerCase();
|
|
||||||
final String target = Text.removeTags(entry.getTarget()).toLowerCase();
|
|
||||||
|
|
||||||
if (target.contains("ring of dueling") && option.contains("remove")) // Incompatible with easyscape
|
|
||||||
{
|
|
||||||
if (client.getLocalPlayer().getWorldLocation().getRegionID() != FIRE_ALTAR)
|
|
||||||
{ //changes duel ring teleport options based on location
|
|
||||||
swap(client, "duel arena", option, target);
|
|
||||||
}
|
|
||||||
else if (client.getLocalPlayer().getWorldLocation().getRegionID() == FIRE_ALTAR)
|
|
||||||
{
|
|
||||||
swap(client, "castle wars", option, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (target.contains("altar") && option.contains("craft")) // Don't accidentally click the altar to craft
|
|
||||||
{
|
|
||||||
hide(option, target);
|
|
||||||
}
|
|
||||||
else if (target.contains("pure") && option.contains("use")) // Don't accidentally use pure essence on altar
|
|
||||||
{
|
|
||||||
hide("use", target);
|
|
||||||
hide("drop", target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hide(String option, String target)
|
|
||||||
{
|
|
||||||
final MenuEntry[] entries = client.getMenuEntries();
|
|
||||||
int index = searchIndex(entries, option, target);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuEntry[] newEntries = new MenuEntry[entries.length - 1];
|
|
||||||
int i2 = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < entries.length - 1; i++)
|
|
||||||
{
|
|
||||||
if (i == index)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
newEntries[i2] = entries[i];
|
|
||||||
i2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.setMenuEntries(newEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int searchIndex(MenuEntry[] entries, String option, String target)
|
|
||||||
{
|
|
||||||
for (int i = entries.length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
MenuEntry entry = entries[i];
|
|
||||||
String entryOption = Text.removeTags(entry.getOption()).toLowerCase();
|
|
||||||
String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase();
|
|
||||||
|
|
||||||
if (entryOption.contains(option.toLowerCase())
|
|
||||||
&& (entryTarget.contains(target)))
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDecorativeObjectSpawned(DecorativeObjectSpawned event)
|
private void onDecorativeObjectSpawned(DecorativeObjectSpawned event)
|
||||||
{
|
{
|
||||||
DecorativeObject decorativeObject = event.getDecorativeObject();
|
final DecorativeObject decorativeObject = event.getDecorativeObject();
|
||||||
if (AbyssRifts.getRift(decorativeObject.getId()) != null)
|
if (AbyssRifts.getRift(decorativeObject.getId()) != null)
|
||||||
{
|
{
|
||||||
abyssObjects.add(decorativeObject);
|
abyssObjects.add(decorativeObject);
|
||||||
@@ -314,13 +216,14 @@ public class RunecraftPlugin extends Plugin
|
|||||||
|
|
||||||
private void onDecorativeObjectDespawned(DecorativeObjectDespawned event)
|
private void onDecorativeObjectDespawned(DecorativeObjectDespawned event)
|
||||||
{
|
{
|
||||||
DecorativeObject decorativeObject = event.getDecorativeObject();
|
final DecorativeObject decorativeObject = event.getDecorativeObject();
|
||||||
abyssObjects.remove(decorativeObject);
|
abyssObjects.remove(decorativeObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onGameStateChanged(GameStateChanged event)
|
private void onGameStateChanged(GameStateChanged event)
|
||||||
{
|
{
|
||||||
GameState gameState = event.getGameState();
|
final GameState gameState = event.getGameState();
|
||||||
|
|
||||||
switch (gameState)
|
switch (gameState)
|
||||||
{
|
{
|
||||||
case LOADING:
|
case LOADING:
|
||||||
@@ -331,34 +234,28 @@ public class RunecraftPlugin extends Plugin
|
|||||||
case LOGIN_SCREEN:
|
case LOGIN_SCREEN:
|
||||||
darkMage = null;
|
darkMage = null;
|
||||||
break;
|
break;
|
||||||
|
case LOGGED_IN:
|
||||||
|
removeSwaps();
|
||||||
|
handleSwaps();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onItemContainerChanged(ItemContainerChanged event)
|
private void onItemContainerChanged(ItemContainerChanged event)
|
||||||
{
|
{
|
||||||
if (event.getItemContainer() == client.getItemContainer(InventoryID.INVENTORY))
|
final ItemContainer container = event.getItemContainer();
|
||||||
{
|
|
||||||
|
|
||||||
final Item[] items = event.getItemContainer().getItems();
|
if (container == client.getItemContainer(InventoryID.INVENTORY))
|
||||||
|
{
|
||||||
|
final Item[] items = container.getItems();
|
||||||
degradedPouchInInventory = Stream.of(items).anyMatch(i -> DEGRADED_POUCHES.contains(i.getId()));
|
degradedPouchInInventory = Stream.of(items).anyMatch(i -> DEGRADED_POUCHES.contains(i.getId()));
|
||||||
}
|
}
|
||||||
else if (event.getItemContainer() == client.getItemContainer(InventoryID.EQUIPMENT))
|
|
||||||
{
|
|
||||||
final Item[] items = event.getItemContainer().getItems();
|
|
||||||
|
|
||||||
if (items.length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wearingTiara = this.Lavas && items[EquipmentInventorySlot.HEAD.getSlotIdx()].getId() == ItemID.FIRE_TIARA;
|
|
||||||
wearingCape = this.Lavas && items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId() == ItemID.RUNECRAFT_CAPE || config.Lavas() && items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId() == ItemID.RUNECRAFT_CAPET || config.Lavas() && items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId() == ItemID.MAX_CAPE_13342;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onNpcSpawned(NpcSpawned event)
|
private void onNpcSpawned(NpcSpawned event)
|
||||||
{
|
{
|
||||||
final NPC npc = event.getNpc();
|
final NPC npc = event.getNpc();
|
||||||
|
|
||||||
if (npc.getId() == NpcID.DARK_MAGE)
|
if (npc.getId() == NpcID.DARK_MAGE)
|
||||||
{
|
{
|
||||||
darkMage = npc;
|
darkMage = npc;
|
||||||
@@ -368,35 +265,61 @@ public class RunecraftPlugin extends Plugin
|
|||||||
private void onNpcDespawned(NpcDespawned event)
|
private void onNpcDespawned(NpcDespawned event)
|
||||||
{
|
{
|
||||||
final NPC npc = event.getNpc();
|
final NPC npc = event.getNpc();
|
||||||
if (npc != null && npc.equals(darkMage))
|
|
||||||
|
if (npc != null && npc == darkMage)
|
||||||
{
|
{
|
||||||
darkMage = null;
|
darkMage = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSwaps()
|
private void handleSwaps()
|
||||||
{
|
{
|
||||||
if (config.essPouch())
|
if (this.essPouch)
|
||||||
{
|
{
|
||||||
menuManager.addSwap("deposit", "pouch", 2, 57, "fill", "pouch", 9, 1007);
|
menuManager.addPriorityEntry(POUCH).setPriority(100);
|
||||||
menuManager.addSwap("fill", "pouch", "empty", "pouch", true, false);
|
menuManager.addPriorityEntry(EMPTY).setPriority(10);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
menuManager.removeSwap("deposit", "pouch", 2, 57, "fill", "pouch", 9, 1007);
|
menuManager.removePriorityEntry(POUCH);
|
||||||
menuManager.removeSwap("fill", "pouch", "empty", "pouch", true, false);
|
menuManager.removePriorityEntry(EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.getLocalPlayer() == null || !this.lavas)
|
||||||
|
{
|
||||||
|
menuManager.removeHiddenEntry("craft", "altar", false, false);
|
||||||
|
menuManager.removeHiddenEntry("use", "pure essence", false, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuManager.addHiddenEntry("craft", "altar", false, false);
|
||||||
|
menuManager.addHiddenEntry("use", "Pure essence", false, true);
|
||||||
|
|
||||||
|
if (client.getLocalPlayer().getWorldLocation().getRegionID() != FIRE_ALTAR)
|
||||||
|
{
|
||||||
|
menuManager.addPriorityEntry(DUEL_ARENA).setPriority(100);
|
||||||
|
menuManager.removePriorityEntry(CASTLE_WARS);
|
||||||
|
}
|
||||||
|
else if (client.getLocalPlayer().getWorldLocation().getRegionID() == FIRE_ALTAR)
|
||||||
|
{
|
||||||
|
menuManager.addPriorityEntry(CASTLE_WARS).setPriority(100);
|
||||||
|
menuManager.removePriorityEntry(DUEL_ARENA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeSwaps()
|
private void removeSwaps()
|
||||||
{
|
{
|
||||||
menuManager.removeSwap("deposit", "pouch", 2, 57, "fill", "pouch", 9, 1007);
|
menuManager.removeHiddenEntry("craft", "altar", false, false);
|
||||||
menuManager.removeSwap("fill", "pouch", "empty", "pouch", true, false);
|
menuManager.removeHiddenEntry("use", "Pure essence", false, true);
|
||||||
|
menuManager.removePriorityEntry(POUCH);
|
||||||
|
menuManager.removePriorityEntry(EMPTY);
|
||||||
|
menuManager.removePriorityEntry(CASTLE_WARS);
|
||||||
|
menuManager.removePriorityEntry(DUEL_ARENA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateConfig()
|
private void updateConfig()
|
||||||
{
|
{
|
||||||
this.Lavas = config.Lavas();
|
this.lavas = config.Lavas();
|
||||||
this.essPouch = config.essPouch();
|
this.essPouch = config.essPouch();
|
||||||
this.hightlightDarkMage = config.hightlightDarkMage();
|
this.hightlightDarkMage = config.hightlightDarkMage();
|
||||||
this.degradingNotification = config.degradingNotification();
|
this.degradingNotification = config.degradingNotification();
|
||||||
|
|||||||
@@ -24,9 +24,19 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.mixins;
|
package net.runelite.mixins;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Named;
|
||||||
import net.runelite.api.ChatMessageType;
|
import net.runelite.api.ChatMessageType;
|
||||||
import net.runelite.api.ClanMember;
|
import net.runelite.api.ClanMember;
|
||||||
import net.runelite.api.EnumDefinition;
|
import net.runelite.api.EnumDefinition;
|
||||||
@@ -91,21 +101,6 @@ import net.runelite.api.events.WidgetLoaded;
|
|||||||
import net.runelite.api.events.WidgetPressed;
|
import net.runelite.api.events.WidgetPressed;
|
||||||
import net.runelite.api.hooks.Callbacks;
|
import net.runelite.api.hooks.Callbacks;
|
||||||
import net.runelite.api.hooks.DrawCallbacks;
|
import net.runelite.api.hooks.DrawCallbacks;
|
||||||
import net.runelite.api.vars.AccountType;
|
|
||||||
import net.runelite.api.widgets.Widget;
|
|
||||||
import net.runelite.api.widgets.WidgetInfo;
|
|
||||||
import net.runelite.api.widgets.WidgetItem;
|
|
||||||
import net.runelite.api.widgets.WidgetType;
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.inject.Named;
|
|
||||||
import net.runelite.api.mixins.Copy;
|
import net.runelite.api.mixins.Copy;
|
||||||
import net.runelite.api.mixins.FieldHook;
|
import net.runelite.api.mixins.FieldHook;
|
||||||
import net.runelite.api.mixins.Inject;
|
import net.runelite.api.mixins.Inject;
|
||||||
@@ -113,8 +108,11 @@ import net.runelite.api.mixins.MethodHook;
|
|||||||
import net.runelite.api.mixins.Mixin;
|
import net.runelite.api.mixins.Mixin;
|
||||||
import net.runelite.api.mixins.Replace;
|
import net.runelite.api.mixins.Replace;
|
||||||
import net.runelite.api.mixins.Shadow;
|
import net.runelite.api.mixins.Shadow;
|
||||||
import net.runelite.rs.api.RSPacketBuffer;
|
import net.runelite.api.vars.AccountType;
|
||||||
import org.slf4j.Logger;
|
import net.runelite.api.widgets.Widget;
|
||||||
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.api.widgets.WidgetItem;
|
||||||
|
import net.runelite.api.widgets.WidgetType;
|
||||||
import net.runelite.rs.api.RSAbstractArchive;
|
import net.runelite.rs.api.RSAbstractArchive;
|
||||||
import net.runelite.rs.api.RSChatChannel;
|
import net.runelite.rs.api.RSChatChannel;
|
||||||
import net.runelite.rs.api.RSClanChat;
|
import net.runelite.rs.api.RSClanChat;
|
||||||
@@ -122,17 +120,19 @@ import net.runelite.rs.api.RSClient;
|
|||||||
import net.runelite.rs.api.RSEnumDefinition;
|
import net.runelite.rs.api.RSEnumDefinition;
|
||||||
import net.runelite.rs.api.RSFriendSystem;
|
import net.runelite.rs.api.RSFriendSystem;
|
||||||
import net.runelite.rs.api.RSFriendsList;
|
import net.runelite.rs.api.RSFriendsList;
|
||||||
import net.runelite.rs.api.RSTileItem;
|
|
||||||
import net.runelite.rs.api.RSIgnoreList;
|
import net.runelite.rs.api.RSIgnoreList;
|
||||||
import net.runelite.rs.api.RSIndexedSprite;
|
import net.runelite.rs.api.RSIndexedSprite;
|
||||||
import net.runelite.rs.api.RSItemContainer;
|
import net.runelite.rs.api.RSItemContainer;
|
||||||
import net.runelite.rs.api.RSNPC;
|
import net.runelite.rs.api.RSNPC;
|
||||||
import net.runelite.rs.api.RSNodeDeque;
|
import net.runelite.rs.api.RSNodeDeque;
|
||||||
import net.runelite.rs.api.RSNodeHashTable;
|
import net.runelite.rs.api.RSNodeHashTable;
|
||||||
|
import net.runelite.rs.api.RSPacketBuffer;
|
||||||
import net.runelite.rs.api.RSPlayer;
|
import net.runelite.rs.api.RSPlayer;
|
||||||
import net.runelite.rs.api.RSSprite;
|
import net.runelite.rs.api.RSSprite;
|
||||||
|
import net.runelite.rs.api.RSTileItem;
|
||||||
import net.runelite.rs.api.RSUsername;
|
import net.runelite.rs.api.RSUsername;
|
||||||
import net.runelite.rs.api.RSWidget;
|
import net.runelite.rs.api.RSWidget;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@Mixin(RSClient.class)
|
@Mixin(RSClient.class)
|
||||||
public abstract class RSClientMixin implements RSClient
|
public abstract class RSClientMixin implements RSClient
|
||||||
@@ -1328,7 +1328,8 @@ public abstract class RSClientMixin implements RSClient
|
|||||||
widgetId,
|
widgetId,
|
||||||
false
|
false
|
||||||
),
|
),
|
||||||
authentic
|
authentic,
|
||||||
|
client.getMouseCurrentButton()
|
||||||
);
|
);
|
||||||
|
|
||||||
client.getCallbacks().post(MenuOptionClicked.class, menuOptionClicked);
|
client.getCallbacks().post(MenuOptionClicked.class, menuOptionClicked);
|
||||||
|
|||||||
Reference in New Issue
Block a user