Merge remote-tracking branch 'upstream/master' into master

This commit is contained in:
ThatGamerBlue
2021-03-31 12:49:31 +01:00
28 changed files with 999 additions and 304 deletions

View File

@@ -25,9 +25,9 @@
object ProjectVersions {
const val launcherVersion = "2.2.0"
const val rlVersion = "1.7.3"
const val rlVersion = "1.7.3.1"
const val openosrsVersion = "4.2.1"
const val openosrsVersion = "4.3.0"
const val rsversion = 194
const val cacheversion = 165

View File

@@ -51,6 +51,20 @@ public interface Scene
int getDrawDistance();
void setDrawDistance(int drawDistance);
/**
* Get the minimum scene level which will be rendered
*
* @return the plane of the minimum level
*/
int getMinLevel();
/**
* Set the minimum scene level which will be rendered
*
* @param minLevel the plane of the minimum level
*/
void setMinLevel(int minLevel);
/**
* Remove a game object from the scene
* @param gameObject

View File

@@ -615,6 +615,15 @@ public enum Varbits
*/
PARASITE(10151),
/**
* Whether the vanilla wiki entity lookup is displayed under the minimap
*
* 0 = Enabled
* 1 = Disabled
*
*/
WIKI_ENTITY_LOOKUP(10113),
/**
* Whether the Special Attack orb is disabled due to being in a PvP area
*

View File

@@ -178,6 +178,7 @@ public class WidgetID
public static final int DIALOG_NOTIFICATION_GROUP_ID = 229;
public static final int DIALOG_SPRITE2_ID = 11;
public static final int MULTISKILL_MENU_GROUP_ID = 270;
public static final int TEMPOROSS_GROUP_ID = 437;
static class WorldMap
{
@@ -1076,6 +1077,10 @@ public class WidgetID
static final int TELEPORT = 59;
}
static class TemporossStatus
{
static final int STATUS_INDICATOR = 4;
}
static class DialogPlayer
{

View File

@@ -542,6 +542,8 @@ public enum WidgetInfo
MULTICOMBAT_RESIZEABLE_MODERN(WidgetID.RESIZABLE_VIEWPORT_BOTTOM_LINE_GROUP_ID, WidgetID.ResizableViewport.MULTICOMBAT_INDICATOR),
MULTICOMBAT_RESIZEABLE_CLASSIC(WidgetID.RESIZABLE_VIEWPORT_OLD_SCHOOL_BOX_GROUP_ID, WidgetID.ResizableViewport.MULTICOMBAT_INDICATOR),
TEMPOROSS_STATUS_INDICATOR(WidgetID.TEMPOROSS_GROUP_ID, WidgetID.TemporossStatus.STATUS_INDICATOR),
//OpenOSRS
WORLD_MAP_BUTTON_BORDER(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB),

View File

@@ -26,9 +26,8 @@
package net.runelite.client.eventbus;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Iterables;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
@@ -183,26 +182,10 @@ public class EventBus
*/
public synchronized void unregister(@Nonnull final Object object)
{
final Multimap<Class<?>, Subscriber> map = HashMultimap.create();
map.putAll(subscribers);
for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
{
for (final Method method : clazz.getDeclaredMethods())
{
final Subscribe sub = method.getAnnotation(Subscribe.class);
if (sub == null)
{
continue;
}
final Class<?> parameterClazz = method.getParameterTypes()[0];
map.remove(parameterClazz, new Subscriber(object, method, sub.priority(), null));
}
}
subscribers = ImmutableMultimap.copyOf(map);
subscribers = ImmutableMultimap.copyOf(Iterables.filter(
subscribers.entries(),
e -> e.getValue().getObject() != object
));
}
public synchronized void unregister(Subscriber sub)
@@ -212,12 +195,10 @@ public class EventBus
return;
}
final Multimap<Class<?>, Subscriber> map = HashMultimap.create();
map.putAll(subscribers);
map.values().remove(sub);
subscribers = ImmutableMultimap.copyOf(map);
subscribers = ImmutableMultimap.copyOf(Iterables.filter(
subscribers.entries(),
e -> sub != e.getValue()
));
}
/**

View File

@@ -28,103 +28,7 @@ import com.google.common.collect.ImmutableMap;
import java.util.Map;
import lombok.Getter;
import net.runelite.api.ItemID;
import static net.runelite.api.NpcID.FISHING_SPOT;
import static net.runelite.api.NpcID.FISHING_SPOT_10513;
import static net.runelite.api.NpcID.FISHING_SPOT_10514;
import static net.runelite.api.NpcID.FISHING_SPOT_10515;
import static net.runelite.api.NpcID.FISHING_SPOT_1497;
import static net.runelite.api.NpcID.FISHING_SPOT_1498;
import static net.runelite.api.NpcID.FISHING_SPOT_1499;
import static net.runelite.api.NpcID.FISHING_SPOT_1510;
import static net.runelite.api.NpcID.FISHING_SPOT_1511;
import static net.runelite.api.NpcID.FISHING_SPOT_1514;
import static net.runelite.api.NpcID.FISHING_SPOT_1517;
import static net.runelite.api.NpcID.FISHING_SPOT_1518;
import static net.runelite.api.NpcID.FISHING_SPOT_1519;
import static net.runelite.api.NpcID.FISHING_SPOT_1520;
import static net.runelite.api.NpcID.FISHING_SPOT_1521;
import static net.runelite.api.NpcID.FISHING_SPOT_1522;
import static net.runelite.api.NpcID.FISHING_SPOT_1523;
import static net.runelite.api.NpcID.FISHING_SPOT_1524;
import static net.runelite.api.NpcID.FISHING_SPOT_1525;
import static net.runelite.api.NpcID.FISHING_SPOT_1528;
import static net.runelite.api.NpcID.FISHING_SPOT_1530;
import static net.runelite.api.NpcID.FISHING_SPOT_1535;
import static net.runelite.api.NpcID.FISHING_SPOT_1536;
import static net.runelite.api.NpcID.FISHING_SPOT_1542;
import static net.runelite.api.NpcID.FISHING_SPOT_1544;
import static net.runelite.api.NpcID.FISHING_SPOT_2653;
import static net.runelite.api.NpcID.FISHING_SPOT_2654;
import static net.runelite.api.NpcID.FISHING_SPOT_2655;
import static net.runelite.api.NpcID.FISHING_SPOT_3317;
import static net.runelite.api.NpcID.FISHING_SPOT_3419;
import static net.runelite.api.NpcID.FISHING_SPOT_3657;
import static net.runelite.api.NpcID.FISHING_SPOT_3913;
import static net.runelite.api.NpcID.FISHING_SPOT_3914;
import static net.runelite.api.NpcID.FISHING_SPOT_3915;
import static net.runelite.api.NpcID.FISHING_SPOT_4079;
import static net.runelite.api.NpcID.FISHING_SPOT_4080;
import static net.runelite.api.NpcID.FISHING_SPOT_4081;
import static net.runelite.api.NpcID.FISHING_SPOT_4082;
import static net.runelite.api.NpcID.FISHING_SPOT_4316;
import static net.runelite.api.NpcID.FISHING_SPOT_4476;
import static net.runelite.api.NpcID.FISHING_SPOT_4477;
import static net.runelite.api.NpcID.FISHING_SPOT_4710;
import static net.runelite.api.NpcID.FISHING_SPOT_4712;
import static net.runelite.api.NpcID.FISHING_SPOT_4713;
import static net.runelite.api.NpcID.FISHING_SPOT_4714;
import static net.runelite.api.NpcID.FISHING_SPOT_5233;
import static net.runelite.api.NpcID.FISHING_SPOT_5234;
import static net.runelite.api.NpcID.FISHING_SPOT_5820;
import static net.runelite.api.NpcID.FISHING_SPOT_5821;
import static net.runelite.api.NpcID.FISHING_SPOT_6488;
import static net.runelite.api.NpcID.FISHING_SPOT_7155;
import static net.runelite.api.NpcID.FISHING_SPOT_7199;
import static net.runelite.api.NpcID.FISHING_SPOT_7200;
import static net.runelite.api.NpcID.FISHING_SPOT_7323;
import static net.runelite.api.NpcID.FISHING_SPOT_7459;
import static net.runelite.api.NpcID.FISHING_SPOT_7460;
import static net.runelite.api.NpcID.FISHING_SPOT_7461;
import static net.runelite.api.NpcID.FISHING_SPOT_7462;
import static net.runelite.api.NpcID.FISHING_SPOT_7465;
import static net.runelite.api.NpcID.FISHING_SPOT_7466;
import static net.runelite.api.NpcID.FISHING_SPOT_7467;
import static net.runelite.api.NpcID.FISHING_SPOT_7469;
import static net.runelite.api.NpcID.FISHING_SPOT_7470;
import static net.runelite.api.NpcID.FISHING_SPOT_7730;
import static net.runelite.api.NpcID.FISHING_SPOT_7731;
import static net.runelite.api.NpcID.FISHING_SPOT_7732;
import static net.runelite.api.NpcID.FISHING_SPOT_7733;
import static net.runelite.api.NpcID.FISHING_SPOT_7946;
import static net.runelite.api.NpcID.FISHING_SPOT_7947;
import static net.runelite.api.NpcID.FISHING_SPOT_8523;
import static net.runelite.api.NpcID.FISHING_SPOT_8525;
import static net.runelite.api.NpcID.FISHING_SPOT_8526;
import static net.runelite.api.NpcID.FISHING_SPOT_8527;
import static net.runelite.api.NpcID.FISHING_SPOT_9171;
import static net.runelite.api.NpcID.FISHING_SPOT_9172;
import static net.runelite.api.NpcID.FISHING_SPOT_9173;
import static net.runelite.api.NpcID.FISHING_SPOT_9174;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1506;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1507;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1508;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1509;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1513;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1515;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1516;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1526;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_1527;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_3417;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_3418;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_6825;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_7463;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_7464;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_7468;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_7676;
import static net.runelite.api.NpcID.ROD_FISHING_SPOT_8524;
import static net.runelite.api.NpcID.FISHING_SPOT_4928;
import static net.runelite.api.NpcID.FISHING_SPOT_6784;
import static net.runelite.api.NpcID.*;
@Getter
public enum FishingSpot
@@ -142,7 +46,7 @@ public enum FishingSpot
FISHING_SPOT_3914, FISHING_SPOT_5820, FISHING_SPOT_7199,
FISHING_SPOT_7460, FISHING_SPOT_7465, FISHING_SPOT_7470,
FISHING_SPOT_7946, FISHING_SPOT_9173, FISHING_SPOT_9174,
FISHING_SPOT_10515
FISHING_SPOT_10515, FISHING_SPOT_10635
),
SHARK("Shark, Bass", "Shark", ItemID.RAW_SHARK,
FISHING_SPOT_1511, FISHING_SPOT_1520, FISHING_SPOT_3419,
@@ -175,6 +79,9 @@ public enum FishingSpot
MINNOW("Minnow", ItemID.MINNOW,
FISHING_SPOT_7730, FISHING_SPOT_7731, FISHING_SPOT_7732, FISHING_SPOT_7733
),
HARPOONFISH("Harpoonfish", ItemID.RAW_HARPOONFISH,
FISHING_SPOT_10565, FISHING_SPOT_10568, FISHING_SPOT_10569
),
INFERNAL_EEL("Infernal Eel", ItemID.INFERNAL_EEL,
ROD_FISHING_SPOT_7676
),

View File

@@ -124,16 +124,17 @@ enum DiscordGameEventType
CITY_LUNAR_ISLE("Lunar Isle" , DiscordAreaType.CITIES, 8253, 8252, 8509, 8508),
CITY_MARIM("Marim", DiscordAreaType.REGIONS, 11051),
CITY_MEIYERDITCH("Meiyerditch" , DiscordAreaType.CITIES, 14132, 14387, 14386, 14385),
CITY_MENAPHOS("Menaphos", DiscordAreaType.CITIES, 12843),
CITY_MISCELLANIA("Miscellania" , DiscordAreaType.CITIES, 10044),
CITY_MOR_UL_REK("Mor Ul Rek" , DiscordAreaType.CITIES, 9808, 9807, 10064, 10063),
CITY_MORTTON("Mort'ton" , DiscordAreaType.CITIES, 13875),
CITY_MOS_LE_HARMLESS("Mos Le'Harmless" , DiscordAreaType.CITIES, 14638, 14639, 14894, 14895, 15151, 15406, 15407),
CITY_MOS_LE_HARMLESS("Mos Le'Harmless" , DiscordAreaType.CITIES, 14637, 14638, 14639, 14894, 14895, 15151, 15406, 15407),
CITY_MOUNT_KARUULM("Mount Karuulm", DiscordAreaType.CITIES, 5179, 4923, 5180),
CITY_MOUNTAIN_CAMP("Mountain Camp", DiscordAreaType.CITIES, 11065),
CITY_MYNYDD("Mynydd", DiscordAreaType.CITIES, 8501),
CITY_NARDAH("Nardah" , DiscordAreaType.CITIES, 13613),
CITY_NEITIZNOT("Neitiznot" , DiscordAreaType.CITIES, 9275),
CITY_PISCARILIUS_HOUSE("Port Piscarilius" , DiscordAreaType.CITIES, 6971, 7227, 6970, 7226),
CITY_PISCARILIUS_HOUSE("Port Piscarilius" , DiscordAreaType.CITIES, 6969, 6971, 7227, 6970, 7225, 7226),
CITY_PISCATORIS("Piscatoris" , DiscordAreaType.CITIES, 9273),
CITY_POLLNIVNEACH("Pollnivneach" , DiscordAreaType.CITIES, 13358),
CITY_PORT_KHAZARD("Port Khazard" , DiscordAreaType.CITIES, 10545),
@@ -163,12 +164,13 @@ enum DiscordGameEventType
CITY_ZULANDRA("Zul-Andra" , DiscordAreaType.CITIES, 8495, 8751),
// Dungeons
DUNGEON_ABANDONED_MINE("Abandoned Mine", DiscordAreaType.DUNGEONS, 13718, 11079, 11078, 11077, 10823, 10822, 10821),
DUNGEON_ABANDONED_MINE("Abandoned Mine", DiscordAreaType.DUNGEONS, 13618, 13718, 11079, 11078, 11077, 10823, 10822, 10821),
DUNGEON_AH_ZA_RHOON("Ah Za Rhoon", DiscordAreaType.DUNGEONS, 11666),
DUNGEON_ANCIENT_CAVERN("Ancient Cavern", DiscordAreaType.DUNGEONS, 6483, 6995),
DUNGEON_APE_ATOLL("Ape Atoll Dungeon", DiscordAreaType.DUNGEONS, 11150, 10894),
DUNGEON_APE_ATOLL_BANANA_PLANTATION("Ape Atoll Banana Plantation", DiscordAreaType.DUNGEONS, 10895),
DUNGEON_ARDY_SEWERS("Ardougne Sewers", DiscordAreaType.DUNGEONS, 10136, 10647),
DUNGEON_ARDY_BASEMENT("West Ardougne Basement", DiscordAreaType.DUNGEONS, 10135),
DUNGEON_ARDY_SEWERS("Ardougne Sewers", DiscordAreaType.DUNGEONS, 10134, 10136, 10391, 10647),
DUNGEON_ASGARNIAN_ICE_CAVES("Asgarnian Ice Caves", DiscordAreaType.DUNGEONS, 11925, 12181),
DUNGEON_BERVIRIUS_TOMB("Tomb of Bervirius", DiscordAreaType.DUNGEONS, 11154),
DUNGEON_BRIMHAVEN("Brimhaven Dungeon", DiscordAreaType.DUNGEONS, 10901, 10900, 10899, 10645, 10644, 10643),
@@ -195,6 +197,7 @@ enum DiscordGameEventType
DUNGEON_ECTOFUNTUS("Ectofuntus", DiscordAreaType.DUNGEONS, 14746),
DUNGEON_EDGEVILLE("Edgeville Dungeon", DiscordAreaType.DUNGEONS, 12441, 12442, 12443, 12698),
DUNGEON_ELEMENTAL_WORKSHOP("Elemental Workshop", DiscordAreaType.DUNGEONS, 10906, 7760),
DUNGEON_ELVEN_RABBIT_CAVE("Elven rabbit cave", DiscordAreaType.DUNGEONS, 13252),
DUNGEON_ENAKHRAS_TEMPLE("Enakhra's Temple", DiscordAreaType.DUNGEONS, 12423),
DUNGEON_EVIL_CHICKENS_LAIR("Evil Chicken's Lair", DiscordAreaType.DUNGEONS, 9796),
DUNGEON_EXPERIMENT_CAVE("Experiment Cave", DiscordAreaType.DUNGEONS, 14235, 13979),
@@ -317,7 +320,7 @@ enum DiscordGameEventType
REGION_AGILITY_PYRAMID("Agility Pyramid", DiscordAreaType.REGIONS, 12105, 13356),
REGION_AIR_ALTAR("Air Altar", DiscordAreaType.REGIONS, 11339),
REGION_AL_KHARID_MINE("Al Kharid Mine", DiscordAreaType.REGIONS, 13107),
REGION_APE_ATOLL("Ape Atoll" , DiscordAreaType.REGIONS, 10795, 10974, 11050),
REGION_APE_ATOLL("Ape Atoll" , DiscordAreaType.REGIONS, 10794, 10795, 10974, 11050),
REGION_ARANDAR("Arandar", DiscordAreaType.REGIONS, 9266, 9267, 9523),
REGION_ASGARNIA("Asgarnia", DiscordAreaType.REGIONS, 11825, 11829, 11830, 12085, 12086),
REGION_BATTLEFIELD("Battlefield", DiscordAreaType.REGIONS, 10034),
@@ -335,6 +338,7 @@ enum DiscordGameEventType
REGION_DEATH_ALTAR("Death Altar", DiscordAreaType.REGIONS, 8779),
REGION_DEATH_PLATEAU("Death Plateau", DiscordAreaType.REGIONS, 11320),
REGION_DENSE_ESSENCE("Dense Essence Mine", DiscordAreaType.REGIONS, 6972),
REGION_DESERT_PLATEAU("Desert Plateau", DiscordAreaType.REGIONS, 13361, 13617),
REGION_DIGSITE("Digsite", DiscordAreaType.REGIONS, 13365),
REGION_DRAGONTOOTH("Dragontooth Island", DiscordAreaType.REGIONS, 15159),
REGION_DRAYNOR_MANOR("Draynor Manor", DiscordAreaType.REGIONS, 12340),
@@ -348,6 +352,7 @@ enum DiscordGameEventType
REGION_FARMING_GUILD("Farming Guild", DiscordAreaType.REGIONS, 4922),
REGION_FELDIP_HILLS("Feldip Hills", DiscordAreaType.REGIONS, 9773, 9774, 10029, 10030, 10285, 10286, 10287, 10542, 10543),
REGION_FENKENSTRAIN("Fenkenstrain's Castle", DiscordAreaType.REGIONS, 14135),
REGION_FIGHT_ARENA("Fight Arena", DiscordAreaType.REGIONS, 10289),
REGION_FIRE_ALTAR("Fire Altar", DiscordAreaType.REGIONS, 10315),
REGION_FISHER_REALM("Fisher Realm", DiscordAreaType.REGIONS, 10569),
REGION_FISHING_GUILD("Fishing Guild", DiscordAreaType.REGIONS, 10293),
@@ -363,6 +368,7 @@ enum DiscordGameEventType
REGION_GRAND_EXCHANGE("Grand Exchange", DiscordAreaType.REGIONS, 12598),
REGION_GWD("God Wars Dungeon", DiscordAreaType.REGIONS, 11578),
REGION_HARMONY("Harmony Island", DiscordAreaType.REGIONS, 15148),
REGION_HAZELMERE("Hazelmere's Island", DiscordAreaType.REGIONS, 10544),
REGION_ICE_PATH("Ice Path", DiscordAreaType.REGIONS, 11322, 11323),
REGION_ICEBERG("Iceberg", DiscordAreaType.REGIONS, 10558, 10559),
REGION_ICYENE_GRAVEYARD("Icyene Graveyard", DiscordAreaType.REGIONS, 14641, 14897, 14898),
@@ -370,9 +376,9 @@ enum DiscordGameEventType
REGION_ISLAND_OF_STONE("Island of Stone", DiscordAreaType.REGIONS, 9790),
REGION_ISLE_OF_SOULS("Isle of Souls", DiscordAreaType.REGIONS, 8236, 8237, 8238, 8491, 8492, 8494, 8747, 8750, 9003, 9004, 9006, 9260, 9261, 9262),
REGION_JIGGIG("Jiggig" , DiscordAreaType.REGIONS, 9775),
REGION_KANDARIN("Kandarin", DiscordAreaType.REGIONS, 9014, 9263, 9264, 9519, 9524, 9527, 9776, 9783, 10037, 10290, 10294, 10546, 10551, 10805),
REGION_KANDARIN("Kandarin", DiscordAreaType.REGIONS, 9268, 9269, 9014, 9263, 9264, 9519, 9524, 9527, 9776, 9783, 10037, 10290, 10294, 10546, 10551, 10805, 11062),
REGION_KARAMJA("Karamja" , DiscordAreaType.REGIONS, 10801, 10802, 11054, 11311, 11312, 11313, 11566, 11567, 11568, 11569, 11822),
REGION_KEBOS_LOWLANDS("Kebos Lowlands", DiscordAreaType.REGIONS, 4665, 4666, 4921, 5178),
REGION_KEBOS_LOWLANDS("Kebos Lowlands", DiscordAreaType.REGIONS, 4665, 4666, 4667, 4921, 5178),
REGION_KEBOS_SWAMP("Kebos Swamp", DiscordAreaType.REGIONS, 4664, 4920, 5174, 5175, 5176, 5430, 5431),
REGION_KHARAZI_JUNGLE("Kharazi Jungle", DiscordAreaType.REGIONS, 11053, 11309, 11565, 11821),
REGION_KHARIDIAN_DESERT("Kharidian Desert", DiscordAreaType.REGIONS, 12587, 12844, 12845, 12846, 12847, 12848, 13100, 13101, 13102, 13103, 13104, 13357, 13359, 13360, 13614, 13615, 13616),
@@ -426,6 +432,7 @@ enum DiscordGameEventType
REGION_TROLL_ARENA("Troll Arena", DiscordAreaType.REGIONS, 11576),
REGION_TROLLHEIM("Trollheim", DiscordAreaType.REGIONS, 11577),
REGION_TROLLWEISS_MTN("Trollweiss Mountain", DiscordAreaType.REGIONS, 11066, 11067, 11068),
REGION_TUTORIAL_ISLAND("Tutorial Island", DiscordAreaType.REGIONS, 12079, 12080, 12335, 12336, 12436, 12592),
REGION_UNDERWATER("Underwater", DiscordAreaType.REGIONS, 15008, 15264),
REGION_WATER_ALTAR("Water Altar", DiscordAreaType.REGIONS, 10827),
REGION_WATERBIRTH_ISLAND("Waterbirth Island", DiscordAreaType.REGIONS, 10042),

View File

@@ -114,6 +114,18 @@ public interface FishingConfig extends Config
return Color.GREEN;
}
@Alpha
@ConfigItem(
keyName = "harpoonfishOverlayColor",
name = "Harpoonfish Overlay",
description = "Color of overlays for bubbling Harpoonfish spots",
position = 6
)
default Color getHarpoonfishOverlayColor()
{
return Color.GREEN;
}
@ConfigItem(
position = 7,
keyName = "statTimeout",

View File

@@ -32,6 +32,7 @@ import lombok.AccessLevel;
import lombok.Setter;
import net.runelite.api.GraphicID;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.client.game.FishingSpot;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
@@ -79,6 +80,8 @@ class FishingSpotMinimapOverlay extends Overlay
Color color = npc.getGraphic() == GraphicID.FLYING_FISH
? config.getMinnowsOverlayColor()
: npc.getId() == NpcID.FISHING_SPOT_10569
? config.getHarpoonfishOverlayColor()
: config.getOverlayColor();
net.runelite.api.Point minimapLocation = npc.getMinimapLocation();

View File

@@ -37,6 +37,7 @@ import lombok.Setter;
import net.runelite.api.Client;
import net.runelite.api.GraphicID;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
@@ -114,6 +115,10 @@ class FishingSpotOverlay extends Overlay
{
color = config.getAerialOverlayColor();
}
else if (spot == FishingSpot.HARPOONFISH && npc.getId() == NpcID.FISHING_SPOT_10569)
{
color = config.getHarpoonfishOverlayColor();
}
else
{
color = config.getOverlayColor();

View File

@@ -32,9 +32,19 @@ import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigSection;
@ConfigGroup("itemCharge")
@ConfigGroup(ItemChargeConfig.GROUP)
public interface ItemChargeConfig extends Config
{
String GROUP = "itemCharge";
String KEY_AMULET_OF_BOUNTY = "amuletOfBounty";
String KEY_AMULET_OF_CHEMISTRY = "amuletOfChemistry";
String KEY_BINDING_NECKLACE = "bindingNecklace";
String KEY_CHRONICLE = "chronicle";
String KEY_DODGY_NECKLACE = "dodgyNecklace";
String KEY_EXPLORERS_RING = "explorerRing";
String KEY_RING_OF_FORGING = "ringOfForging";
@ConfigSection(
name = "Charge Settings",
description = "Configuration for which charges should be displayed",
@@ -129,24 +139,6 @@ public interface ItemChargeConfig extends Config
return true;
}
@ConfigItem(
keyName = "dodgyNecklace",
name = "",
description = "",
hidden = true
)
default int dodgyNecklace()
{
return -1;
}
@ConfigItem(
keyName = "dodgyNecklace",
name = "",
description = ""
)
void dodgyNecklace(int dodgyNecklace);
@ConfigItem(
keyName = "showImpCharges",
name = "Imp-in-a-box charges",
@@ -255,24 +247,6 @@ public interface ItemChargeConfig extends Config
return true;
}
@ConfigItem(
keyName = "amuletOfChemistry",
name = "",
description = "",
hidden = true
)
default int amuletOfChemistry()
{
return -1;
}
@ConfigItem(
keyName = "amuletOfChemistry",
name = "",
description = ""
)
void amuletOfChemistry(int amuletOfChemistry);
@ConfigItem(
keyName = "showAmuletOfBountyCharges",
name = "Amulet of Bounty Charges",
@@ -285,24 +259,6 @@ public interface ItemChargeConfig extends Config
return true;
}
@ConfigItem(
keyName = "amuletOfBounty",
name = "",
description = "",
hidden = true
)
default int amuletOfBounty()
{
return -1;
}
@ConfigItem(
keyName = "amuletOfBounty",
name = "",
description = ""
)
void amuletOfBounty(int amuletOfBounty);
@ConfigItem(
keyName = "recoilNotification",
name = "Ring of Recoil Notification",
@@ -327,24 +283,6 @@ public interface ItemChargeConfig extends Config
return true;
}
@ConfigItem(
keyName = "bindingNecklace",
name = "",
description = "",
hidden = true
)
default int bindingNecklace()
{
return -1;
}
@ConfigItem(
keyName = "bindingNecklace",
name = "",
description = ""
)
void bindingNecklace(int bindingNecklace);
@ConfigItem(
keyName = "bindingNotification",
name = "Binding Necklace Notification",
@@ -369,24 +307,6 @@ public interface ItemChargeConfig extends Config
return true;
}
@ConfigItem(
keyName = "explorerRing",
name = "",
description = "",
hidden = true
)
default int explorerRing()
{
return -1;
}
@ConfigItem(
keyName = "explorerRing",
name = "",
description = ""
)
void explorerRing(int explorerRing);
@ConfigItem(
keyName = "showRingOfForgingCount",
name = "Ring of Forging Charges",
@@ -399,24 +319,6 @@ public interface ItemChargeConfig extends Config
return true;
}
@ConfigItem(
keyName = "ringOfForging",
name = "",
description = "",
hidden = true
)
default int ringOfForging()
{
return -1;
}
@ConfigItem(
keyName = "ringOfForging",
name = "",
description = ""
)
void ringOfForging(int ringOfForging);
@ConfigItem(
keyName = "ringOfForgingNotification",
name = "Ring of Forging Notification",
@@ -451,22 +353,4 @@ public interface ItemChargeConfig extends Config
{
return false;
}
@ConfigItem(
keyName = "chronicle",
name = "",
description = "",
hidden = true
)
default int chronicle()
{
return -1;
}
@ConfigItem(
keyName = "chronicle",
name = "",
description = ""
)
void chronicle(int chronicle);
}

View File

@@ -69,7 +69,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.dodgyNecklace();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_DODGY_NECKLACE);
}
else if (itemId == ItemID.BINDING_NECKLACE)
{
@@ -78,7 +78,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.bindingNecklace();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_BINDING_NECKLACE);
}
else if (itemId >= ItemID.EXPLORERS_RING_1 && itemId <= ItemID.EXPLORERS_RING_4)
{
@@ -87,7 +87,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.explorerRing();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_EXPLORERS_RING);
}
else if (itemId == ItemID.RING_OF_FORGING)
{
@@ -96,7 +96,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.ringOfForging();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_RING_OF_FORGING);
}
else if (itemId == ItemID.AMULET_OF_CHEMISTRY)
{
@@ -105,7 +105,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.amuletOfChemistry();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY);
}
else if (itemId == ItemID.AMULET_OF_BOUNTY)
{
@@ -114,7 +114,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.amuletOfBounty();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_AMULET_OF_BOUNTY);
}
else if (itemId == ItemID.CHRONICLE)
{
@@ -123,7 +123,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
return;
}
charges = config.chronicle();
charges = itemChargePlugin.getItemCharges(ItemChargeConfig.KEY_CHRONICLE);
}
else
{

View File

@@ -129,6 +129,9 @@ public class ItemChargePlugin extends Plugin
@Inject
private ClientThread clientThread;
@Inject
private ConfigManager configManager;
@Inject
private OverlayManager overlayManager;
@@ -173,7 +176,7 @@ public class ItemChargePlugin extends Plugin
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (!event.getGroup().equals("itemCharge"))
if (!event.getGroup().equals(ItemChargeConfig.GROUP))
{
return;
}
@@ -310,7 +313,7 @@ public class ItemChargePlugin extends Plugin
}
else if (bindingNecklaceUsedMatcher.find())
{
updateBindingNecklaceCharges(config.bindingNecklace() - 1);
updateBindingNecklaceCharges(getItemCharges(ItemChargeConfig.KEY_BINDING_NECKLACE) - 1);
}
else if (bindingNecklaceCheckMatcher.find())
{
@@ -347,7 +350,7 @@ public class ItemChargePlugin extends Plugin
if (equipment.contains(ItemID.RING_OF_FORGING))
{
int charges = Ints.constrainToRange(config.ringOfForging() - 1, 0, MAX_RING_OF_FORGING_CHARGES);
int charges = Ints.constrainToRange(getItemCharges(ItemChargeConfig.KEY_RING_OF_FORGING) - 1, 0, MAX_RING_OF_FORGING_CHARGES);
updateRingOfForgingCharges(charges);
}
}
@@ -366,28 +369,28 @@ public class ItemChargePlugin extends Plugin
if (match.equals("one"))
{
config.chronicle(1);
setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 1);
}
else
{
config.chronicle(Integer.parseInt(match));
setItemCharges(ItemChargeConfig.KEY_CHRONICLE, Integer.parseInt(match));
}
}
else if (chronicleUseAndCheckMatcher.find())
{
config.chronicle(Integer.parseInt(chronicleUseAndCheckMatcher.group(1)));
setItemCharges(ItemChargeConfig.KEY_CHRONICLE, Integer.parseInt(chronicleUseAndCheckMatcher.group(1)));
}
else if (message.equals(CHRONICLE_ONE_CHARGE_TEXT))
{
config.chronicle(1);
setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 1);
}
else if (message.equals(CHRONICLE_EMPTY_TEXT) || message.equals(CHRONICLE_NO_CHARGES_TEXT))
{
config.chronicle(0);
setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 0);
}
else if (message.equals(CHRONICLE_FULL_TEXT))
{
config.chronicle(1000);
setItemCharges(ItemChargeConfig.KEY_CHRONICLE, 1000);
}
}
}
@@ -501,7 +504,7 @@ public class ItemChargePlugin extends Plugin
private void updateDodgyNecklaceCharges(final int value)
{
config.dodgyNecklace(value);
setItemCharges(ItemChargeConfig.KEY_DODGY_NECKLACE, value);
if (config.showInfoboxes() && config.showDodgyCount())
{
@@ -518,7 +521,7 @@ public class ItemChargePlugin extends Plugin
private void updateAmuletOfChemistryCharges(final int value)
{
config.amuletOfChemistry(value);
setItemCharges(ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, value);
if (config.showInfoboxes() && config.showAmuletOfChemistryCharges())
{
@@ -535,7 +538,7 @@ public class ItemChargePlugin extends Plugin
private void updateAmuletOfBountyCharges(final int value)
{
config.amuletOfBounty(value);
setItemCharges(ItemChargeConfig.KEY_AMULET_OF_BOUNTY, value);
if (config.showInfoboxes() && config.showAmuletOfBountyCharges())
{
@@ -552,7 +555,7 @@ public class ItemChargePlugin extends Plugin
private void updateBindingNecklaceCharges(final int value)
{
config.bindingNecklace(value);
setItemCharges(ItemChargeConfig.KEY_BINDING_NECKLACE, value);
if (config.showInfoboxes() && config.showBindingNecklaceCharges())
{
@@ -570,7 +573,7 @@ public class ItemChargePlugin extends Plugin
private void updateExplorerRingCharges(final int value)
{
// Note: Varbit counts upwards. We count down from the maximum charges.
config.explorerRing(MAX_EXPLORER_RING_CHARGES - value);
setItemCharges(ItemChargeConfig.KEY_EXPLORERS_RING, MAX_EXPLORER_RING_CHARGES - value);
if (config.showInfoboxes() && config.showExplorerRingCharges())
{
@@ -587,7 +590,7 @@ public class ItemChargePlugin extends Plugin
private void updateRingOfForgingCharges(final int value)
{
config.ringOfForging(value);
setItemCharges(ItemChargeConfig.KEY_RING_OF_FORGING, value);
if (config.showInfoboxes() && config.showRingOfForgingCount())
{
@@ -654,27 +657,27 @@ public class ItemChargePlugin extends Plugin
{
if (id == ItemID.DODGY_NECKLACE && type == ItemWithSlot.DODGY_NECKLACE)
{
charges = config.dodgyNecklace();
charges = getItemCharges(ItemChargeConfig.KEY_DODGY_NECKLACE);
}
else if (id == ItemID.BINDING_NECKLACE && type == ItemWithSlot.BINDING_NECKLACE)
{
charges = config.bindingNecklace();
charges = getItemCharges(ItemChargeConfig.KEY_BINDING_NECKLACE);
}
else if ((id >= ItemID.EXPLORERS_RING_1 && id <= ItemID.EXPLORERS_RING_4) && type == ItemWithSlot.EXPLORER_RING)
{
charges = config.explorerRing();
charges = getItemCharges(ItemChargeConfig.KEY_EXPLORERS_RING);
}
else if (id == ItemID.RING_OF_FORGING && type == ItemWithSlot.RING_OF_FORGING)
{
charges = config.ringOfForging();
charges = getItemCharges(ItemChargeConfig.KEY_RING_OF_FORGING);
}
else if (id == ItemID.AMULET_OF_CHEMISTRY && type == ItemWithSlot.AMULET_OF_CHEMISTY)
{
charges = config.amuletOfChemistry();
charges = getItemCharges(ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY);
}
else if (id == ItemID.AMULET_OF_BOUNTY && type == ItemWithSlot.AMULET_OF_BOUNTY)
{
charges = config.amuletOfBounty();
charges = getItemCharges(ItemChargeConfig.KEY_AMULET_OF_BOUNTY);
}
}
else if (itemWithCharge.getType() == type.getType())
@@ -693,6 +696,26 @@ public class ItemChargePlugin extends Plugin
infoBoxManager.addInfoBox(infobox);
}
int getItemCharges(String key)
{
// Migrate old non-profile configurations
Integer i = configManager.getConfiguration(ItemChargeConfig.GROUP, key, Integer.class);
if (i != null)
{
configManager.unsetConfiguration(ItemChargeConfig.GROUP, key);
configManager.setRSProfileConfiguration(ItemChargeConfig.GROUP, key, i);
return i;
}
i = configManager.getRSProfileConfiguration(ItemChargeConfig.GROUP, key, Integer.class);
return i == null ? -1 : i;
}
private void setItemCharges(String key, int value)
{
configManager.setRSProfileConfiguration(ItemChargeConfig.GROUP, key, value);
}
private void removeInfobox(final ItemWithSlot item)
{
infoBoxManager.removeIf(t -> t instanceof ItemChargeInfobox && ((ItemChargeInfobox) t).getItem() == item);

View File

@@ -41,6 +41,7 @@ import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
@@ -239,6 +240,12 @@ public class LootTrackerPlugin extends Plugin
private static final String SPOILS_OF_WAR_EVENT = "Spoils of war";
private static final Set<Integer> SOUL_WARS_REGIONS = ImmutableSet.of(8493, 8749, 9005);
// Tempoross
private static final String TEMPOROSS_EVENT = "Reward pool (Tempoross)";
private static final String TEMPOROSS_CASKET_EVENT = "Casket (Tempoross)";
private static final String TEMPOROSS_LOOT_STRING = "You found some loot: ";
private static final int TEMPOROSS_REGION = 12588;
private static final Set<Character> VOWELS = ImmutableSet.of('a', 'e', 'i', 'o', 'u');
@Inject
@@ -756,6 +763,12 @@ public class LootTrackerPlugin extends Plugin
setEvent(LootRecordType.EVENT, type, client.getBoostedSkillLevel(Skill.HUNTER));
takeInventorySnapshot();
}
if (regionID == TEMPOROSS_REGION && message.startsWith(TEMPOROSS_LOOT_STRING))
{
setEvent(LootRecordType.EVENT, TEMPOROSS_EVENT, client.getBoostedSkillLevel(Skill.FISHING));
takeInventorySnapshot();
}
}
@Subscribe
@@ -772,10 +785,6 @@ public class LootTrackerPlugin extends Plugin
|| HALLOWED_SEPULCHRE_COFFIN_EVENT.equals(eventType)
|| HERBIBOAR_EVENT.equals(eventType)
|| HESPORI_EVENT.equals(eventType)
|| SEEDPACK_EVENT.equals(eventType)
|| CASKET_EVENT.equals(eventType)
|| BIRDNEST_EVENT.equals(eventType)
|| SPOILS_OF_WAR_EVENT.equals(eventType)
|| eventType.endsWith("Bird House")
|| eventType.startsWith("H.A.M. chest")
|| lootRecordType == LootRecordType.PICKPOCKET)
@@ -786,6 +795,17 @@ public class LootTrackerPlugin extends Plugin
processInventoryLoot(eventType, lootRecordType, metadata, event.getItemContainer(), groundItems);
resetEvent();
}
// Events that do not produce ground items
else if (SEEDPACK_EVENT.equals(eventType)
|| CASKET_EVENT.equals(eventType)
|| BIRDNEST_EVENT.equals(eventType)
|| SPOILS_OF_WAR_EVENT.equals(eventType)
|| TEMPOROSS_EVENT.equals(eventType)
|| TEMPOROSS_CASKET_EVENT.equals(eventType))
{
processInventoryLoot(eventType, lootRecordType, metadata, event.getItemContainer(), Collections.emptyList());
resetEvent();
}
}
@Subscribe
@@ -827,6 +847,12 @@ public class LootTrackerPlugin extends Plugin
setEvent(LootRecordType.EVENT, SPOILS_OF_WAR_EVENT);
takeInventorySnapshot();
}
if (event.getMenuOption().equals("Open") && event.getId() == ItemID.CASKET_25590)
{
setEvent(LootRecordType.EVENT, TEMPOROSS_CASKET_EVENT);
takeInventorySnapshot();
}
}
@Schedule(

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, 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.lowmemory;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(LowMemoryConfig.GROUP)
public interface LowMemoryConfig extends Config
{
String GROUP = "lowmemory";
@ConfigItem(
keyName = "lowDetail",
name = "Low detail",
description = "Hides ground detail and simplifies textures.",
position = 0
)
default boolean lowDetail()
{
return true;
}
@ConfigItem(
keyName = "hideLowerPlanes",
name = "Hide lower planes",
description = "Only renders the current plane you are on.",
position = 1
)
default boolean hideLowerPlanes()
{
return false;
}
}

View File

@@ -24,12 +24,16 @@
*/
package net.runelite.client.plugins.lowmemory;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.events.BeforeRender;
import net.runelite.api.events.GameStateChanged;
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.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@@ -47,12 +51,15 @@ public class LowMemoryPlugin extends Plugin
@Inject
private ClientThread clientThread;
@Inject
private LowMemoryConfig config;
@Override
protected void startUp()
{
if (client.getGameState() == GameState.LOGGED_IN)
{
clientThread.invoke(() -> client.changeMemoryMode(true));
clientThread.invoke(() -> client.changeMemoryMode(config.lowDetail()));
}
}
@@ -62,6 +69,21 @@ public class LowMemoryPlugin extends Plugin
clientThread.invoke(() -> client.changeMemoryMode(false));
}
@Provides
LowMemoryConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(LowMemoryConfig.class);
}
@Subscribe
public void onConfigChanged(ConfigChanged configChanged)
{
if (configChanged.getGroup().equals(LowMemoryConfig.GROUP))
{
clientThread.invoke(() -> client.changeMemoryMode(config.lowDetail()));
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
@@ -70,7 +92,16 @@ public class LowMemoryPlugin extends Plugin
// which breaks the gpu plugin due to it requiring the 128x128px textures
if (event.getGameState() == GameState.LOGIN_SCREEN)
{
client.changeMemoryMode(true);
client.changeMemoryMode(config.lowDetail());
}
}
@Subscribe
public void onBeforeRender(BeforeRender beforeRender)
{
// This needs to be set to the current plane, but there is no event for plane change, so
// just set it each render.
client.getScene().
setMinLevel(config.hideLowerPlanes() ? client.getPlane() : 0);
}
}

View File

@@ -38,6 +38,7 @@ import net.runelite.api.NPCComposition;
import net.runelite.api.ObjectComposition;
import net.runelite.api.ScriptID;
import net.runelite.api.SpriteID;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
@@ -131,7 +132,7 @@ public class WikiPlugin extends Plugin
children[0] = null;
Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER);
if (vanilla != null)
if (vanilla != null && client.getVar(Varbits.WIKI_ENTITY_LOOKUP) == 0)
{
vanilla.setHidden(false);
}

View File

@@ -101,6 +101,8 @@ enum FishingSpotLocation
JATISZO(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
new WorldPoint(2400, 3780, 0), new WorldPoint(2412, 3780, 0),
new WorldPoint(2419, 3789, 0)),
KHARIDIAN_DESERT_SOUTH_WEST(FishingSpot.LOBSTER,
new WorldPoint(3139, 2800, 0)),
KINGSTOWN_EAST(FishingSpot.SALMON, new WorldPoint(1723, 3685, 0)),
LANDS_END_EAST(FishingSpot.SHRIMP, new WorldPoint(1534, 3414, 0)),
LANDS_END_WEST(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER, FishingSpot.SHRIMP},
@@ -162,6 +164,10 @@ enum FishingSpotLocation
TAVERLEY_DUNGEON(FishingSpot.LAVA_EEL,
new WorldPoint(2893, 9764, 0), new WorldPoint(2889, 9766, 0),
new WorldPoint(2883, 9765, 0)),
TEMPOROSS(FishingSpot.HARPOONFISH,
new WorldPoint(3047, 3002, 0), new WorldPoint(3050, 2995, 0),
new WorldPoint(3036, 2996, 0), new WorldPoint(3035, 2962, 0),
new WorldPoint(3047, 2957, 0), new WorldPoint(3045, 2954, 0)),
TREE_GNOME_STRONGHOLD(FishingSpot.SALMON,
new WorldPoint(2389, 3422, 0), new WorldPoint(2382, 3415, 0)),
TUTORIAL_ISLAND(FishingSpot.TUTORIAL_SHRIMP, new WorldPoint(3100, 3091, 0)),

View File

@@ -183,6 +183,8 @@ enum MiningSiteLocation
RIMMINGTON(new WorldPoint(2977, 3240, 0),
new Rock(2, Ore.CLAY), new Rock(5, Ore.COPPER), new Rock(2, Ore.TIN), new Rock(6, Ore.IRON),
new Rock(2, Ore.GOLD)),
RUINS_OF_UNKAH(new WorldPoint(3172, 2871, 0),
new Rock(1, Ore.COPPER), new Rock(1, Ore.TIN), new Rock(5, Ore.IRON), new Rock(2, Ore.SILVER), new Rock(1, Ore.COAL)),
SALT_MINE(new WorldPoint(2835, 10334, 0),
new Rock(7, Ore.BASALT), new Rock(15, Ore.TE_SALT), new Rock(12, Ore.EFH_SALT), new Rock(12, Ore.URT_SALT)),
SHAYZIEN_EAST(new WorldPoint(1597, 3653, 0), new Rock(3, Ore.CLAY), new Rock(1, Ore.MITHRIL), new Rock(1, Ore.ADAMANTITE)),

View File

@@ -121,6 +121,10 @@ enum TransportationPointLocation
CHARTER_PRIFDDINAS("Charter Ship", new WorldPoint(2156, 3331, 0)),
CHARTER_PRIFDDINAS_INSTANCE("Charter Ship", new WorldPoint(3180, 6083, 0)),
//Ferries
FERRY_AL_KHARID("Ferry to Ruins of Unkah", new WorldPoint(3269, 3142, 0), new WorldPoint(3145, 2843, 0)),
FERRY_RUINS_OF_UNKAH("Ferry to Al Kharid", new WorldPoint(3145, 2843, 0), new WorldPoint(3269, 3142, 0)),
//Minecarts/Carts
MINE_CART_ARCEUUS("Lovakengj Minecart Network", new WorldPoint(1673, 3832, 0)),
MINE_CART_GRANDEXCHANGE("Minecart to Keldagrim", new WorldPoint(3139, 3504, 0)),

View File

@@ -268,15 +268,13 @@ public class XpGlobesOverlay extends Overlay
}
final int size = orbSize - config.progressArcStrokeWidth();
final int width = (int) (size * GLOBE_ICON_RATIO);
final int height = (int) (size * GLOBE_ICON_RATIO);
if (width <= 0 || height <= 0)
final int scaledIconSize = (int) (size * GLOBE_ICON_RATIO);
if (scaledIconSize <= 0)
{
return null;
}
icon = ImageUtil.resizeImage(icon, width, height);
icon = ImageUtil.resizeImage(icon, scaledIconSize, scaledIconSize, true);
xpGlobe.setSkillIcon(icon);
xpGlobe.setSize(orbSize);

View File

@@ -66,7 +66,8 @@ public class WidgetOverlay extends Overlay
new WidgetOverlay(client, WidgetInfo.VOLCANIC_MINE_STABILITY_INFOBOX_GROUP, OverlayPosition.BOTTOM_LEFT),
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_FIXED, OverlayPosition.BOTTOM_RIGHT),
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_MODERN, OverlayPosition.CANVAS_TOP_RIGHT),
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_CLASSIC, OverlayPosition.CANVAS_TOP_RIGHT)
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_CLASSIC, OverlayPosition.CANVAS_TOP_RIGHT),
new WidgetOverlay(client, WidgetInfo.TEMPOROSS_STATUS_INDICATOR, OverlayPosition.TOP_LEFT)
);
}

View File

@@ -211,7 +211,38 @@ public class ImageUtil
*/
public static BufferedImage resizeImage(final BufferedImage image, final int newWidth, final int newHeight)
{
final Image resized = image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
return resizeImage(image, newWidth, newHeight, false);
}
/**
* Re-size a BufferedImage to the given dimensions.
*
* @param image the BufferedImage.
* @param newWidth The width to set the BufferedImage to.
* @param newHeight The height to set the BufferedImage to.
* @param preserveAspectRatio Whether to preserve the original image's aspect ratio. When {@code true}, the image
* will be scaled to have a maximum of {@code newWidth} width and {@code newHeight}
* height.
* @return The BufferedImage with the specified dimensions
*/
public static BufferedImage resizeImage(final BufferedImage image, final int newWidth, final int newHeight, final boolean preserveAspectRatio)
{
final Image resized;
if (preserveAspectRatio)
{
if (image.getWidth() > image.getHeight())
{
resized = image.getScaledInstance(newWidth, -1, Image.SCALE_SMOOTH);
}
else
{
resized = image.getScaledInstance(-1, newHeight, Image.SCALE_SMOOTH);
}
}
else
{
resized = image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
}
return ImageUtil.bufferedImageFromImage(resized);
}

View File

@@ -102,6 +102,7 @@ public class WSClient extends WebSocketListener implements AutoCloseable
Request request = new Request.Builder()
.url(RuneLiteAPI.getWsEndpoint())
.header("User-Agent", RuneLiteAPI.userAgent)
.build();
webSocket = okHttpClient.newWebSocket(request, this);

View File

@@ -0,0 +1,272 @@
/*
* 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.itemcharges;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.util.concurrent.ScheduledExecutorService;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.InventoryID;
import net.runelite.api.ItemContainer;
import net.runelite.api.ItemID;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ItemChargePluginTest
{
private static final String CHECK = "Your dodgy necklace has 10 charges left.";
private static final String PROTECT = "Your dodgy necklace protects you. It has 9 charges left.";
private static final String PROTECT_1 = "Your dodgy necklace protects you. <col=ff0000>It has 1 charge left.</col>";
private static final String BREAK = "Your dodgy necklace protects you. <col=ff0000>It then crumbles to dust.</col>";
private static final String CHECK_RING_OF_FORGING_FULL = "You can smelt 140 more pieces of iron ore before a ring melts.";
private static final String CHECK_RING_OF_FORGING_ONE = "You can smelt one more piece of iron ore before a ring melts.";
private static final String USED_RING_OF_FORGING = "You retrieve a bar of iron.";
private static final String BREAK_RING_OF_FORGING = "<col=7f007f>Your Ring of Forging has melted.</col>";
private static final String CHECK_AMULET_OF_CHEMISTRY = "Your amulet of chemistry has 5 charges left.";
private static final String CHECK_AMULET_OF_CHEMISTRY_1 = "Your amulet of chemistry has 1 charge left.";
private static final String USED_AMULET_OF_CHEMISTRY = "Your amulet of chemistry helps you create a 4-dose potion. It has 4 charges left.";
private static final String USED_AMULET_OF_CHEMISTRY_3_DOSES = "Your amulet of chemistry helps you create a 3-dose potion. It has 2 charges left.";
private static final String USED_AMULET_OF_CHEMISTRY_2_DOSES = "Your amulet of chemistry helps you create a 2-dose potion. It has one charge left.";
private static final String BREAK_AMULET_OF_CHEMISTRY = "Your amulet of chemistry helps you create a 4-dose potion. It then crumbles to dust.";
private static final String BREAK_AMULET_OF_CHEMISTRY_3_DOSES = "Your amulet of chemistry helps you create a 3-dose potion. It then crumbles to dust.";
private static final String BREAK_AMULET_OF_CHEMISTRY_2_DOSES = "Your amulet of chemistry helps you create a 2-dose potion. It then crumbles to dust.";
private static final String CHRONICLE_CHECK_CHARGES_FULL = "Your book has 1000 charges left.";
private static final String CHRONICLE_CHECK_CHARGES_ONE = "You have one charge left in your book.";
private static final String CHRONICLE_CHECK_CHARGES_EMPTY = "Your book has run out of charges.";
private static final String CHRONICLE_TELEPORT = "<col=ef1020>Your book has 999 charges left.</col>";
private static final String CHRONICLE_TELEPORT_ONE = "<col=ef1020>You have one charge left in your book.</col>";
private static final String CHRONICLE_TELEPORT_EMPTY = "<col=ef1020>Your book has run out of charges.</col>";
private static final String CHRONICLE_TELEPORT_FAIL = "Your book does not have any charges. Purchase some Teleport Cards from Diango.";
private static final String CHRONICLE_ADD_SINGLE_CHARGE = "You add a single charge to your book. It now has one charge.";
private static final String CHRONICLE_ADD_SINGLE_CHARGE_FULL = "You add a single charge to your book. It now has 1000 charges.";
private static final String CHRONICLE_ADD_MULTIPLE_CHARGES = "You add 5 charges to your book. It now has 5 charges.";
private static final String CHRONICLE_ADD_FULL = "Your book is fully charged! It has 1,000 charges already.";
@Mock
@Bind
private Client client;
@Mock
@Bind
private ScheduledExecutorService scheduledExecutorService;
@Mock
@Bind
private RuneLiteConfig runeLiteConfig;
@Mock
@Bind
private OverlayManager overlayManager;
@Mock
@Bind
private Notifier notifier;
@Mock
@Bind
private InfoBoxManager infoBoxManager;
@Mock
@Bind
private ItemChargeConfig config;
@Mock
@Bind
private ConfigManager configManager;
@Inject
private ItemChargePlugin itemChargePlugin;
@Before
public void before()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
@Test
public void testOnChatMessage()
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHECK, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_DODGY_NECKLACE, 10);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", PROTECT, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_DODGY_NECKLACE, 9);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", PROTECT_1, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_DODGY_NECKLACE, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", BREAK, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_DODGY_NECKLACE, 10);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHECK_RING_OF_FORGING_ONE, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_RING_OF_FORGING, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHECK_RING_OF_FORGING_FULL, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_RING_OF_FORGING, 140);
reset(configManager);
when(configManager.getRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_RING_OF_FORGING, Integer.class)).thenReturn(90);
// Create equipment inventory with ring of forging
ItemContainer equipmentItemContainer = mock(ItemContainer.class);
when(client.getItemContainer(InventoryID.EQUIPMENT)).thenReturn(equipmentItemContainer);
when(equipmentItemContainer.contains(ItemID.RING_OF_FORGING)).thenReturn(true);
// Run message
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", USED_RING_OF_FORGING, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_RING_OF_FORGING, 89);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", BREAK_RING_OF_FORGING, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_RING_OF_FORGING, 140);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHECK_AMULET_OF_CHEMISTRY, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 5);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHECK_AMULET_OF_CHEMISTRY_1, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", USED_AMULET_OF_CHEMISTRY, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 4);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", USED_AMULET_OF_CHEMISTRY_3_DOSES, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 2);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", USED_AMULET_OF_CHEMISTRY_2_DOSES, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", BREAK_AMULET_OF_CHEMISTRY, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 5);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", BREAK_AMULET_OF_CHEMISTRY_3_DOSES, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 5);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", BREAK_AMULET_OF_CHEMISTRY_2_DOSES, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_AMULET_OF_CHEMISTRY, 5);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_CHECK_CHARGES_FULL, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1000);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_CHECK_CHARGES_ONE, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_CHECK_CHARGES_EMPTY, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 0);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_TELEPORT, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 999);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_TELEPORT_ONE, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_TELEPORT_EMPTY, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 0);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_TELEPORT_FAIL, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 0);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_ADD_SINGLE_CHARGE, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_ADD_SINGLE_CHARGE_FULL, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1000);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_ADD_MULTIPLE_CHARGES, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 5);
reset(configManager);
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", CHRONICLE_ADD_FULL, "", 0);
itemChargePlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration(ItemChargeConfig.GROUP, ItemChargeConfig.KEY_CHRONICLE, 1000);
reset(configManager);
}
}

View File

@@ -0,0 +1,410 @@
/*
* Copyright (c) 2020, 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.loottracker;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemComposition;
import net.runelite.api.ItemContainer;
import net.runelite.api.ItemID;
import net.runelite.api.IterableHashTable;
import net.runelite.api.MessageNode;
import net.runelite.api.Player;
import net.runelite.api.Skill;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.WidgetID;
import net.runelite.client.account.SessionManager;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.ItemStack;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.loottracker.LootRecordType;
import net.runelite.http.api.loottracker.LootTrackerClient;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isNull;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class LootTrackerPluginTest
{
private static final Map<Integer, String> HERB_IDS_TO_NAMES = ImmutableMap.<Integer, String>builder()
.put(ItemID.GRIMY_GUAM_LEAF, "Grimy guam leaf")
.put(ItemID.GRIMY_MARRENTILL, "Grimy marrentill")
.put(ItemID.GRIMY_TARROMIN, "Grimy tarromin")
.put(ItemID.GRIMY_HARRALANDER, "Grimy harralander")
.put(ItemID.GRIMY_RANARR_WEED, "Grimy ranarr weed")
.put(ItemID.GRIMY_IRIT_LEAF, "Grimy irit leaf")
.put(ItemID.GRIMY_AVANTOE, "Grimy avantoe")
.put(ItemID.GRIMY_KWUARM, "Grimy kwuarm")
.put(ItemID.GRIMY_SNAPDRAGON, "Grimy snapdragon")
.put(ItemID.GRIMY_CADANTINE, "Grimy cadantine")
.put(ItemID.GRIMY_LANTADYME, "Grimy lantadyme")
.put(ItemID.GRIMY_DWARF_WEED, "Grimy dwarf weed")
.put(ItemID.GRIMY_TORSTOL, "Grimy torstol")
.build();
@Mock
@Bind
private ScheduledExecutorService scheduledExecutorService;
@Mock
@Bind
private Client client;
@Mock
@Bind
private SpriteManager spriteManager;
@Mock
@Bind
private InfoBoxManager infoBoxManager;
@Inject
private LootTrackerPlugin lootTrackerPlugin;
@Mock
@Bind
private LootTrackerConfig lootTrackerConfig;
@Mock
@Bind
private SessionManager sessionManager;
@Mock
@Bind
private ItemManager itemManager;
@Mock
@Bind
private ChatMessageManager chatMessageManager;
@Mock
@Bind
private LootTrackerClient lootTrackerClient;
@Before
public void setUp()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
Player player = mock(Player.class);
when(player.getWorldLocation()).thenReturn(new WorldPoint(0, 0, 0));
when(client.getLocalPlayer()).thenReturn(player);
}
@Test
public void testPickPocket()
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You pick the hero's pocket.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Hero", lootTrackerPlugin.eventType);
assertEquals(LootRecordType.PICKPOCKET, lootTrackerPlugin.lootRecordType);
}
@Test
public void testFirstClue()
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You have completed 1 master Treasure Trail.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Clue Scroll (Master)", lootTrackerPlugin.eventType);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType);
}
private static ItemComposition mockItem(String name)
{
ItemComposition itemComposition = mock(ItemComposition.class);
when(itemComposition.getName()).thenReturn(name);
return itemComposition;
}
@Test
public void testHerbiboarHerbSack()
{
when(client.getBoostedSkillLevel(Skill.HERBLORE)).thenReturn(42);
for (Map.Entry<Integer, String> herb : HERB_IDS_TO_NAMES.entrySet())
{
final int id = herb.getKey();
final String name = herb.getValue();
final String herbMessage = String.format("You put the %s herb into your herb sack.", name);
final String herbFullMessage = String.format("Your herb sack is too full to hold the %s herb.", name);
final ItemPrice herbPrice = new ItemPrice();
herbPrice.setId(id);
herbPrice.setName(name);
when(itemManager.search(name)).thenReturn(Collections.singletonList(herbPrice));
MessageNode node = mock(MessageNode.class);
when(node.getType()).thenReturn(ChatMessageType.SPAM);
when(node.getValue()).thenReturn(herbMessage);
MessageNode nodeFull = mock(MessageNode.class);
when(nodeFull.getType()).thenReturn(ChatMessageType.SPAM);
when(nodeFull.getValue()).thenReturn(herbFullMessage);
IterableHashTable<MessageNode> messageTable = mock(IterableHashTable.class);
Iterator<MessageNode> mockIterator = mock(Iterator.class);
when(mockIterator.hasNext()).thenReturn(true, true, false);
when(mockIterator.next()).thenReturn(node).thenReturn(nodeFull);
when(messageTable.iterator()).thenReturn(mockIterator);
when(client.getMessages()).thenReturn(messageTable);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin);
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", LootTrackerPlugin.HERBIBOAR_LOOTED_MESSAGE, "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage);
verify(lootTrackerPluginSpy).addLoot("Herbiboar", -1, LootRecordType.EVENT, 42, Arrays.asList(
new ItemStack(id, 1, null),
new ItemStack(id, 1, null)
));
// Check the event type is null, which means the plugin isn't waiting on an inventory change event
assertNull(lootTrackerPlugin.eventType);
}
}
@Test
public void testCoXRaidsLootValue()
{
when(lootTrackerConfig.showRaidsLootValue()).thenReturn(true);
when(lootTrackerConfig.priceType()).thenReturn(LootTrackerPriceType.GRAND_EXCHANGE);
LootTrackerPlugin spyPlugin = Mockito.spy(lootTrackerPlugin);
// Make sure we don't execute addLoot, so we don't have to mock LootTrackerPanel and everything else also
doNothing().when(spyPlugin).addLoot(anyString(), anyInt(), any(LootRecordType.class), isNull(), anyCollection());
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.TWISTED_BOW, 1),
new Item(ItemID.PURE_ESSENCE, 42)
});
when(client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST)).thenReturn(itemContainer);
when(itemManager.getItemPrice(ItemID.TWISTED_BOW)).thenReturn(1_100_000_000);
when(itemManager.getItemPrice(ItemID.PURE_ESSENCE)).thenReturn(6);
WidgetLoaded widgetLoaded = new WidgetLoaded();
widgetLoaded.setGroupId(WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID);
spyPlugin.onWidgetLoaded(widgetLoaded);
ArgumentCaptor<QueuedMessage> captor = ArgumentCaptor.forClass(QueuedMessage.class);
verify(chatMessageManager).queue(captor.capture());
QueuedMessage queuedMessage = captor.getValue();
assertEquals("<colNORMAL>Your loot is worth around <colHIGHLIGHT>1,100,000,252<colNORMAL> coins.", queuedMessage.getRuneLiteFormattedMessage());
}
@Test
public void testToBRaidsLootValue()
{
when(lootTrackerConfig.priceType()).thenReturn(LootTrackerPriceType.HIGH_ALCHEMY);
when(lootTrackerConfig.showRaidsLootValue()).thenReturn(true);
LootTrackerPlugin spyPlugin = Mockito.spy(lootTrackerPlugin);
// Make sure we don't execute addLoot, so we don't have to mock LootTrackerPanel and everything else also
doNothing().when(spyPlugin).addLoot(anyString(), anyInt(), any(LootRecordType.class), isNull(), anyCollection());
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.SCYTHE_OF_VITUR, 1),
new Item(ItemID.MAHOGANY_SEED, 10)
});
when(client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST)).thenReturn(itemContainer);
ItemComposition compScythe = mock(ItemComposition.class);
when(itemManager.getItemComposition(ItemID.SCYTHE_OF_VITUR)).thenReturn(compScythe);
when(compScythe.getHaPrice()).thenReturn(60_000_000);
ItemComposition compSeed = mock(ItemComposition.class);
when(itemManager.getItemComposition(ItemID.MAHOGANY_SEED)).thenReturn(compSeed);
when(compSeed.getHaPrice()).thenReturn(2_102);
when(client.getBaseX()).thenReturn(3232);
when(client.getBaseY()).thenReturn(4320);
LocalPoint localPoint = new LocalPoint(0, 0);
when(client.getLocalPlayer().getLocalLocation()).thenReturn(localPoint);
WidgetLoaded widgetLoaded = new WidgetLoaded();
widgetLoaded.setGroupId(WidgetID.THEATRE_OF_BLOOD_GROUP_ID);
spyPlugin.onWidgetLoaded(widgetLoaded);
ArgumentCaptor<QueuedMessage> captor = ArgumentCaptor.forClass(QueuedMessage.class);
verify(chatMessageManager).queue(captor.capture());
QueuedMessage queuedMessage = captor.getValue();
assertEquals("<colNORMAL>Your loot is worth around <colHIGHLIGHT>60,021,020<colNORMAL> coins.", queuedMessage.getRuneLiteFormattedMessage());
}
@Test
public void testBirdhouses()
{
// No bird nests
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving 10 dead birds, 30 feathers and 1140 Hunter XP.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Magic Bird House", lootTrackerPlugin.eventType);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType);
// Single bird nest
chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving a nest, 10 dead birds, 50 feathers and 700 Hunter XP.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Teak Bird House", lootTrackerPlugin.eventType);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType);
// Multiple nests
chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You dismantle and discard the trap, retrieving 2 nests, 10 dead birds, 40 feathers and 280 Hunter XP.", "", 0);
lootTrackerPlugin.onChatMessage(chatMessage);
assertEquals("Regular Bird House", lootTrackerPlugin.eventType);
assertEquals(LootRecordType.EVENT, lootTrackerPlugin.lootRecordType);
}
@Test
public void testGrubbyChest()
{
Player player = mock(Player.class);
when(player.getWorldLocation()).thenReturn(new WorldPoint(7323 >> 2, (7323 & 0xff) << 6, 0));
when(client.getLocalPlayer()).thenReturn(player);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin);
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.TWISTED_BOW, 1),
new Item(ItemID.GRUBBY_KEY, 1)
});
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(itemContainer);
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You unlock the chest with your key.", "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.TWISTED_BOW, 1)
});
lootTrackerPluginSpy.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer));
chatMessage = new ChatMessage(null, ChatMessageType.GAMEMESSAGE, "", "You have opened the Grubby Chest 2 times.", "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.TWISTED_BOW, 1),
new Item(ItemID.SHARK, 42)
});
lootTrackerPluginSpy.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer));
verify(lootTrackerPluginSpy).addLoot("Grubby Chest", -1, LootRecordType.EVENT, null, Arrays.asList(
new ItemStack(ItemID.SHARK, 42, null)
));
}
@Test
public void testTemporossRewardPool()
{
Player player = mock(Player.class);
when(client.getLocalPlayer()).thenReturn(player);
when(client.getLocalPlayer().getWorldLocation()).thenReturn(new WorldPoint(3153, 2833, 0));
when(client.getBoostedSkillLevel(Skill.FISHING)).thenReturn(69);
LootTrackerPlugin lootTrackerPluginSpy = spy(this.lootTrackerPlugin);
doNothing().when(lootTrackerPluginSpy).addLoot(any(), anyInt(), any(), any(), any(Collection.class));
ItemContainer itemContainer = mock(ItemContainer.class);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.BUCKET_OF_WATER, 1),
new Item(ItemID.ROPE, 1)
});
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(itemContainer);
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You found some loot: 30 x Raw tuna", "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.BUCKET_OF_WATER, 1),
new Item(ItemID.ROPE, 1),
new Item(ItemID.RAW_TUNA, 30)
});
lootTrackerPluginSpy.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer));
verify(lootTrackerPluginSpy).addLoot("Reward pool (Tempoross)", -1, LootRecordType.EVENT, 69, Arrays.asList(
new ItemStack(ItemID.RAW_TUNA, 30, null)
));
chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", "You found some loot: <col=ef1020>Tome of water (empty)</col>", "", 0);
lootTrackerPluginSpy.onChatMessage(chatMessage);
when(itemContainer.getItems()).thenReturn(new Item[]{
new Item(ItemID.BUCKET_OF_WATER, 1),
new Item(ItemID.ROPE, 1),
new Item(ItemID.RAW_TUNA, 30),
new Item(ItemID.TOME_OF_WATER_EMPTY, 1)
});
lootTrackerPluginSpy.onItemContainerChanged(new ItemContainerChanged(InventoryID.INVENTORY.getId(), itemContainer));
verify(lootTrackerPluginSpy).addLoot("Reward pool (Tempoross)", -1, LootRecordType.EVENT, 69, Arrays.asList(
new ItemStack(ItemID.TOME_OF_WATER_EMPTY, 1, null)
));
}
}

View File

@@ -44,6 +44,9 @@ public interface RSScene extends Scene
@Import("minPlane")
int getMinLevel();
@Import("minPlane")
void setMinLevel(int lvl);
@Import("newGroundItemPile")
void newGroundItemPile(int plane, int x, int y, int hash, RSRenderable var5, long var6, RSRenderable var7, RSRenderable var8);