diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt
index fc294eb7ee..e0b2d427a7 100644
--- a/buildSrc/src/main/kotlin/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/Dependencies.kt
@@ -25,7 +25,7 @@
object ProjectVersions {
const val launcherVersion = "2.2.0"
- const val rlVersion = "1.8.14"
+ const val rlVersion = "1.8.15"
const val openosrsVersion = "4.20.5"
diff --git a/runelite-api/src/main/java/net/runelite/api/ItemID.java b/runelite-api/src/main/java/net/runelite/api/ItemID.java
index 108c3af9dd..954e2a13bc 100644
--- a/runelite-api/src/main/java/net/runelite/api/ItemID.java
+++ b/runelite-api/src/main/java/net/runelite/api/ItemID.java
@@ -179,7 +179,7 @@ public final class ItemID
public static final int BLUE_GOBLIN_MAIL = 287;
public static final int GOBLIN_MAIL = 288;
public static final int RESEARCH_PACKAGE = 290;
- public static final int NOTES = 291;
+ public static final int RESEARCH_NOTES = 291;
public static final int BOOK_ON_BAXTORIAN = 292;
public static final int KEY_293 = 293;
public static final int GLARIALS_PEBBLE = 294;
@@ -870,6 +870,7 @@ public final class ItemID
public static final int WATER_TALISMAN = 1444;
public static final int BODY_TALISMAN = 1446;
public static final int MIND_TALISMAN = 1448;
+ public static final int BLOOD_TALISMAN = 1450;
public static final int CHAOS_TALISMAN = 1452;
public static final int COSMIC_TALISMAN = 1454;
public static final int DEATH_TALISMAN = 1456;
@@ -3311,6 +3312,7 @@ public final class ItemID
public static final int CHAOS_TIARA = 5543;
public static final int LAW_TIARA = 5545;
public static final int DEATH_TIARA = 5547;
+ public static final int BLOOD_TIARA = 5549;
public static final int ROGUE_TOP = 5553;
public static final int ROGUE_MASK = 5554;
public static final int ROGUE_TROUSERS = 5555;
@@ -6539,7 +6541,7 @@ public final class ItemID
public static final int BAR_MAGNET = 10489;
public static final int UNDEAD_TWIGS = 10490;
public static final int BLESSED_AXE = 10491;
- public static final int RESEARCH_NOTES = 10492;
+ public static final int RESEARCH_NOTES_10492 = 10492;
public static final int TRANSLATED_NOTES = 10493;
public static final int A_PATTERN = 10494;
public static final int A_CONTAINER = 10495;
@@ -9275,7 +9277,7 @@ public final class ItemID
public static final int RUBY_KEY = 20767;
public static final int EMERALD_KEY = 20768;
public static final int SAPPHIRE_KEY = 20769;
- public static final int NOTES_20770 = 20770;
+ public static final int NOTES = 20770;
public static final int NOTES_20771 = 20771;
public static final int NOTES_20772 = 20772;
public static final int BANSHEE_MASK = 20773;
@@ -10234,7 +10236,7 @@ public final class ItemID
public static final int THE_WILD_HUNT = 22512;
public static final int VERZIK_VITUR__PATIENT_RECORD = 22514;
public static final int DAWNBRINGER = 22516;
- public static final int VERZIKS_CRYSTAL_SHARD = 22517;
+ public static final int ESCAPE_CRYSTAL = 22517;
public static final int CABBAGE_22519 = 22519;
public static final int CABBAGE_22520 = 22520;
public static final int COIN_POUCH = 22521;
@@ -12021,7 +12023,7 @@ public final class ItemID
public static final int CORRUPTED_PADDLEFISH = 25958;
public static final int CORRUPTED_ESCAPE_CRYSTAL = 25959;
public static final int CRYSTAL_PADDLEFISH = 25960;
- public static final int ESCAPE_CRYSTAL = 25961;
+ public static final int ESCAPE_CRYSTAL_25961 = 25961;
public static final int CRYPT_KEY = 25963;
public static final int RANIS_HEAD = 25964;
public static final int STRANGE_SPIDER_EGGS = 25965;
@@ -12402,5 +12404,205 @@ public final class ItemID
public static final int LOOT_KEY_26653 = 26653;
public static final int LOOT_KEY_26654 = 26654;
public static final int LOOT_KEY_26655 = 26655;
+ public static final int SHOE_26656 = 26656;
+ public static final int SHOE_26657 = 26657;
+ public static final int SHOE_26658 = 26658;
+ public static final int SHOE_26659 = 26659;
+ public static final int SHOE_26660 = 26660;
+ public static final int SHOE_26661 = 26661;
+ public static final int SHOE_26662 = 26662;
+ public static final int SHOE_26663 = 26663;
+ public static final int SHOE_26664 = 26664;
+ public static final int SHOE_26665 = 26665;
+ public static final int SHOE_26666 = 26666;
+ public static final int SHOE_26667 = 26667;
+ public static final int SHOE_26668 = 26668;
+ public static final int SHOE_26669 = 26669;
+ public static final int SHOE_26670 = 26670;
+ public static final int SHOE_26671 = 26671;
+ public static final int SHOE_26672 = 26672;
+ public static final int SHOE_26673 = 26673;
+ public static final int SLAYER_HELMET_I_26674 = 26674;
+ public static final int BLACK_SLAYER_HELMET_I_26675 = 26675;
+ public static final int GREEN_SLAYER_HELMET_I_26676 = 26676;
+ public static final int RED_SLAYER_HELMET_I_26677 = 26677;
+ public static final int PURPLE_SLAYER_HELMET_I_26678 = 26678;
+ public static final int TURQUOISE_SLAYER_HELMET_I_26679 = 26679;
+ public static final int HYDRA_SLAYER_HELMET_I_26680 = 26680;
+ public static final int TWISTED_SLAYER_HELMET_I_26681 = 26681;
+ public static final int TZTOK_SLAYER_HELMET_I_26682 = 26682;
+ public static final int VAMPYRIC_SLAYER_HELMET_I_26683 = 26683;
+ public static final int TZKAL_SLAYER_HELMET_I_26684 = 26684;
+ public static final int GRANITE_RING_I_26685 = 26685;
+ public static final int MAOMAS_MED_HELM_BROKEN = 26686;
+ public static final int MAOMAS_FULL_HELM_BROKEN = 26687;
+ public static final int MAOMAS_GREAT_HELM_BROKEN = 26688;
+ public static final int CALAMITY_CHEST_BROKEN = 26689;
+ public static final int SUPERIOR_CALAMITY_CHEST_BROKEN = 26690;
+ public static final int ELITE_CALAMITY_CHEST_BROKEN = 26691;
+ public static final int CALAMITY_BREECHES_BROKEN = 26692;
+ public static final int SUPERIOR_CALAMITY_BREECHES_BROKEN = 26693;
+ public static final int ELITE_CALAMITY_BREECHES_BROKEN = 26694;
+ public static final int CENTURION_CUIRASS_BROKEN = 26695;
+ public static final int WRISTBANDS_OF_THE_ARENA_BROKEN = 26696;
+ public static final int HARDENED_WRISTBANDS_OF_THE_ARENA_BROKEN = 26697;
+ public static final int KORIFFS_HEADBAND_BROKEN = 26698;
+ public static final int KORIFFS_COWL_BROKEN = 26699;
+ public static final int KORIFFS_COIF_BROKEN = 26700;
+ public static final int SAIKAS_HOOD_BROKEN = 26701;
+ public static final int SAIKAS_VEIL_BROKEN = 26702;
+ public static final int SAIKAS_SHROUD_BROKEN = 26703;
+ public static final int BLIGHTED_WAVE_SACK = 26704;
+ public static final int BLIGHTED_SURGE_SACK = 26705;
+ public static final int SCROLL_OF_IMBUING = 26706;
+ public static final int DRAGON_CLAWS_ORNAMENT_KIT = 26707;
+ public static final int DRAGON_CLAWS_OR = 26708;
+ public static final int DRAGON_WARHAMMER_ORNAMENT_KIT = 26709;
+ public static final int DRAGON_WARHAMMER_OR = 26710;
+ public static final int HEAVY_BALLISTA_ORNAMENT_KIT = 26711;
+ public static final int HEAVY_BALLISTA_OR = 26712;
+ public static final int ARMADYL_ARMOUR_ORNAMENT_KIT = 26713;
+ public static final int ARMADYL_HELMET_OR = 26714;
+ public static final int ARMADYL_CHESTPLATE_OR = 26715;
+ public static final int ARMADYL_CHAINSKIRT_OR = 26716;
+ public static final int BANDOS_ARMOUR_ORNAMENT_KIT = 26717;
+ public static final int BANDOS_CHESTPLATE_OR = 26718;
+ public static final int BANDOS_TASSETS_OR = 26719;
+ public static final int BANDOS_BOOTS_OR = 26720;
+ public static final int CENTURION_CUIRASS = 26721;
+ public static final int CENTURION_CUIRASS_L = 26722;
+ public static final int WRISTBANDS_OF_THE_ARENA = 26723;
+ public static final int WRISTBANDS_OF_THE_ARENA_L = 26724;
+ public static final int WRISTBANDS_OF_THE_ARENA_C = 26725;
+ public static final int WRISTBANDS_OF_THE_ARENA_CL = 26726;
+ public static final int WRISTBANDS_OF_THE_ARENA_I = 26727;
+ public static final int WRISTBANDS_OF_THE_ARENA_IL = 26728;
+ public static final int WRISTBANDS_OF_THE_ARENA_IC = 26729;
+ public static final int WRISTBANDS_OF_THE_ARENA_ILC = 26730;
+ public static final int SAIKAS_HOOD = 26731;
+ public static final int SAIKAS_HOOD_L = 26732;
+ public static final int SAIKAS_VEIL = 26733;
+ public static final int SAIKAS_VEIL_L = 26734;
+ public static final int SAIKAS_SHROUD = 26735;
+ public static final int SAIKAS_SHROUD_L = 26736;
+ public static final int KORIFFS_HEADBAND = 26737;
+ public static final int KORIFFS_HEADBAND_L = 26738;
+ public static final int KORIFFS_COWL = 26739;
+ public static final int KORIFFS_COWL_L = 26740;
+ public static final int KORIFFS_COIF = 26741;
+ public static final int KORIFFS_COIF_L = 26742;
+ public static final int MAOMAS_MED_HELM = 26743;
+ public static final int MAOMAS_MED_HELM_L = 26744;
+ public static final int MAOMAS_FULL_HELM = 26745;
+ public static final int MAOMAS_FULL_HELM_L = 26746;
+ public static final int MAOMAS_GREAT_HELM = 26747;
+ public static final int MAOMAS_GREAT_HELM_L = 26748;
+ public static final int CALAMITY_CHEST = 26749;
+ public static final int CALAMITY_CHEST_L = 26750;
+ public static final int SUPERIOR_CALAMITY_CHEST = 26751;
+ public static final int SUPERIOR_CALAMITY_CHEST_L = 26752;
+ public static final int ELITE_CALAMITY_CHEST = 26753;
+ public static final int ELITE_CALAMITY_CHEST_L = 26754;
+ public static final int CALAMITY_BREECHES = 26755;
+ public static final int CALAMITY_BREECHES_L = 26756;
+ public static final int SUPERIOR_CALAMITY_BREECHES = 26757;
+ public static final int SUPERIOR_CALAMITY_BREECHES_L = 26758;
+ public static final int ELITE_CALAMITY_BREECHES = 26759;
+ public static final int ELITE_CALAMITY_BREECHES_L = 26760;
+ public static final int RING_OF_SUFFERING_I_26761 = 26761;
+ public static final int RING_OF_SUFFERING_RI_26762 = 26762;
+ public static final int SALVE_AMULETI_26763 = 26763;
+ public static final int RING_OF_THE_GODS_I_26764 = 26764;
+ public static final int TYRANNICAL_RING_I_26765 = 26765;
+ public static final int TREASONOUS_RING_I_26766 = 26766;
+ public static final int SEERS_RING_I_26767 = 26767;
+ public static final int ARCHERS_RING_I_26768 = 26768;
+ public static final int WARRIOR_RING_I_26769 = 26769;
+ public static final int BERSERKER_RING_I_26770 = 26770;
+ public static final int BLACK_MASK_10_I_26771 = 26771;
+ public static final int BLACK_MASK_9_I_26772 = 26772;
+ public static final int BLACK_MASK_8_I_26773 = 26773;
+ public static final int BLACK_MASK_7_I_26774 = 26774;
+ public static final int BLACK_MASK_6_I_26775 = 26775;
+ public static final int BLACK_MASK_5_I_26776 = 26776;
+ public static final int BLACK_MASK_4_I_26777 = 26777;
+ public static final int BLACK_MASK_3_I_26778 = 26778;
+ public static final int BLACK_MASK_2_I_26779 = 26779;
+ public static final int BLACK_MASK_1_I_26780 = 26780;
+ public static final int BLACK_MASK_I_26781 = 26781;
+ public static final int SALVE_AMULETEI_26782 = 26782;
+ public static final int COLOSSAL_POUCH = 26784;
+ public static final int COLOSSAL_POUCH_26786 = 26786;
+ public static final int GOLD_TIARA = 26788;
+ public static final int ABYSSAL_PEARLS = 26792;
+ public static final int CATALYTIC_TALISMAN = 26798;
+ public static final int CATALYTIC_TIARA = 26801;
+ public static final int ELEMENTAL_TIARA = 26804;
+ public static final int ABYSSAL_GREEN_DYE = 26807;
+ public static final int ABYSSAL_BLUE_DYE = 26809;
+ public static final int ABYSSAL_RED_DYE = 26811;
+ public static final int ABYSSAL_NEEDLE = 26813;
+ public static final int RING_OF_THE_ELEMENTS = 26815;
+ public static final int RING_OF_THE_ELEMENTS_26818 = 26818;
+ public static final int GUARDIANS_EYE = 26820;
+ public static final int ABYSSAL_LANTERN = 26822;
+ public static final int ABYSSAL_LANTERN_NORMAL_LOGS = 26824;
+ public static final int ABYSSAL_LANTERN_BLUE_LOGS = 26826;
+ public static final int ABYSSAL_LANTERN_RED_LOGS = 26828;
+ public static final int ABYSSAL_LANTERN_WHITE_LOGS = 26830;
+ public static final int ABYSSAL_LANTERN_PURPLE_LOGS = 26832;
+ public static final int ABYSSAL_LANTERN_GREEN_LOGS = 26834;
+ public static final int ABYSSAL_LANTERN_OAK_LOGS = 26836;
+ public static final int ABYSSAL_LANTERN_WILLOW_LOGS = 26838;
+ public static final int ABYSSAL_LANTERN_MAPLE_LOGS = 26840;
+ public static final int ABYSSAL_LANTERN_YEW_LOGS = 26842;
+ public static final int ABYSSAL_LANTERN_BLISTERWOOD_LOGS = 26844;
+ public static final int ABYSSAL_LANTERN_MAGIC_LOGS = 26846;
+ public static final int ABYSSAL_LANTERN_REDWOOD_LOGS = 26848;
+ public static final int HAT_OF_THE_EYE = 26850;
+ public static final int ROBE_TOP_OF_THE_EYE = 26852;
+ public static final int ROBE_BOTTOMS_OF_THE_EYE = 26854;
+ public static final int BOOTS_OF_THE_EYE = 26856;
+ public static final int HAT_OF_THE_EYE_RED = 26858;
+ public static final int ROBE_TOP_OF_THE_EYE_RED = 26860;
+ public static final int ROBE_BOTTOMS_OF_THE_EYE_RED = 26862;
+ public static final int HAT_OF_THE_EYE_GREEN = 26864;
+ public static final int ROBE_TOP_OF_THE_EYE_GREEN = 26866;
+ public static final int ROBE_BOTTOMS_OF_THE_EYE_GREEN = 26868;
+ public static final int HAT_OF_THE_EYE_BLUE = 26870;
+ public static final int ROBE_TOP_OF_THE_EYE_BLUE = 26872;
+ public static final int ROBE_BOTTOMS_OF_THE_EYE_BLUE = 26874;
+ public static final int ATLAXS_DIARY = 26876;
+ public static final int GUARDIAN_FRAGMENTS = 26878;
+ public static final int GUARDIAN_ESSENCE = 26879;
+ public static final int CATALYTIC_GUARDIAN_STONE = 26880;
+ public static final int ELEMENTAL_GUARDIAN_STONE = 26881;
+ public static final int UNCHARGED_CELL = 26882;
+ public static final int WEAK_CELL = 26883;
+ public static final int MEDIUM_CELL = 26884;
+ public static final int STRONG_CELL = 26885;
+ public static final int OVERCHARGED_CELL = 26886;
+ public static final int PORTAL_TALISMAN_AIR = 26887;
+ public static final int PORTAL_TALISMAN_WATER = 26888;
+ public static final int PORTAL_TALISMAN_EARTH = 26889;
+ public static final int PORTAL_TALISMAN_FIRE = 26890;
+ public static final int PORTAL_TALISMAN_MIND = 26891;
+ public static final int PORTAL_TALISMAN_CHAOS = 26892;
+ public static final int PORTAL_TALISMAN_DEATH = 26893;
+ public static final int PORTAL_TALISMAN_BLOOD = 26894;
+ public static final int PORTAL_TALISMAN_BODY = 26895;
+ public static final int PORTAL_TALISMAN_COSMIC = 26896;
+ public static final int PORTAL_TALISMAN_NATURE = 26897;
+ public static final int PORTAL_TALISMAN_LAW = 26898;
+ public static final int GREATISH_GUARDIAN = 26899;
+ public static final int ABYSSAL_PROTECTOR = 26901;
+ public static final int EYE_AMULET = 26903;
+ public static final int STRONG_CUP_OF_TEA = 26904;
+ public static final int ABYSSAL_INCANTATION = 26905;
+ public static final int COLOSSAL_POUCH_26906 = 26906;
+ public static final int INTRICATE_POUCH = 26908;
+ public static final int TARNISHED_LOCKET = 26910;
+ public static final int LOST_BAG = 26912;
+ public static final int AMULET_OF_THE_EYE = 26914;
/* This file is automatically generated. Do not edit. */
}
\ No newline at end of file
diff --git a/runelite-api/src/main/java/net/runelite/api/NpcID.java b/runelite-api/src/main/java/net/runelite/api/NpcID.java
index 043207441e..6e12c89f91 100644
--- a/runelite-api/src/main/java/net/runelite/api/NpcID.java
+++ b/runelite-api/src/main/java/net/runelite/api/NpcID.java
@@ -2709,7 +2709,6 @@ public final class NpcID
public static final int LOWE = 2883;
public static final int SHOP_KEEPER_2884 = 2884;
public static final int SHOP_ASSISTANT_2885 = 2885;
- public static final int AUBURY = 2886;
public static final int ASYFF = 2887;
public static final int SHOP_KEEPER_2888 = 2888;
public static final int GRUM_2889 = 2889;
@@ -3019,7 +3018,7 @@ public final class NpcID
public static final int WOODSMAN_TUTOR = 3226;
public static final int BANKER_TUTOR = 3227;
public static final int ELLIS = 3231;
- public static final int WIZARD_3232 = 3232;
+ public static final int WIZARD_JALARAST = 3232;
public static final int LEECH = 3233;
public static final int FERAL_VAMPYRE_3234 = 3234;
public static final int BEE_KEEPER = 3235;
@@ -3035,7 +3034,6 @@ public final class NpcID
public static final int FARMER_3245 = 3245;
public static final int WIZARD_FRUMSCONE = 3246;
public static final int WIZARD_AKUTHA = 3247;
- public static final int WIZARD_DISTENTOR = 3248;
public static final int WIZARD_SININA = 3249;
public static final int FARMER_3250 = 3250;
public static final int FARMER_3251 = 3251;
@@ -4609,8 +4607,7 @@ public final class NpcID
public static final int GNOME_SOLDIER_4910 = 4910;
public static final int GNOME_SOLDIER_4911 = 4911;
public static final int HEALTHORG_AND_TORTOISE = 4912;
- public static final int BRIMSTAIL = 4913;
- public static final int BRIMSTAIL_4914 = 4914;
+ public static final int BRIMSTAIL = 4914;
public static final int GARV = 4915;
public static final int GRUBOR = 4916;
public static final int TROBERT = 4917;
@@ -4706,7 +4703,6 @@ public final class NpcID
public static final int COMBAT_STONE_5031 = 5031;
public static final int COMBAT_STONE_5032 = 5032;
public static final int COMBAT_STONE_5033 = 5033;
- public static final int SEDRIDOR = 5034;
public static final int JULIET = 5035;
public static final int APOTHECARY = 5036;
public static final int ROMEO = 5037;
@@ -4744,7 +4740,7 @@ public final class NpcID
public static final int FISHERMAN_5078 = 5078;
public static final int DELRITH = 5079;
public static final int WEAKENED_DELRITH = 5080;
- public static final int TRAIBORN = 5081;
+ public static final int WIZARD_TRAIBORN = 5081;
public static final int GYPSY_ARIS = 5082;
public static final int SIR_PRYSIN = 5083;
public static final int SIR_PRYSIN_5084 = 5084;
@@ -5544,7 +5540,6 @@ public final class NpcID
public static final int AGILITY_TRAINER_5927 = 5927;
public static final int WEREWOLF_5928 = 5928;
public static final int KNIGHT_5929 = 5929;
- public static final int RICK_5931 = 5931;
public static final int EGG_5932 = 5932;
public static final int EGG_5933 = 5933;
public static final int EGG_5934 = 5934;
@@ -9007,7 +9002,7 @@ public final class NpcID
public static final int BARBARIAN_10678 = 10678;
public static final int BARBARIAN_10679 = 10679;
public static final int GUARD_10680 = 10680;
- public static final int AUBURY_10681 = 10681;
+ public static final int AUBURY = 10681;
public static final int RAT_10682 = 10682;
public static final int BARAEK_10683 = 10683;
public static final int RAMARNO_10684 = 10684;
@@ -9620,15 +9615,55 @@ public final class NpcID
public static final int DIPFLIP = 11383;
public static final int OLDAK_11384 = 11384;
public static final int OLDAK_11385 = 11385;
- public static final int LARRY_LEPRECHAUN = 11399;
- public static final int FISHING_SPOT_11400 = 11400;
- public static final int BIG_DAVE_11401 = 11401;
- public static final int CAPT_ARNAV_11402 = 11402;
- public static final int MY_ARM_11403 = 11403;
- public static final int COOK_11404 = 11404;
- public static final int WISE_OLD_MAN_11405 = 11405;
- public static final int HANS_11406 = 11406;
- public static final int HASSAN_11407 = 11407;
- public static final int LEPRECHAUN = 11408;
+ public static final int WIZARD_DISTENTOR = 11399;
+ public static final int WIZARD_DISTENTOR_11400 = 11400;
+ public static final int GREATISH_GUARDIAN = 11401;
+ public static final int ABYSSAL_PROTECTOR = 11402;
+ public static final int THE_GREAT_GUARDIAN = 11403;
+ public static final int APPRENTICE_FELIX = 11404;
+ public static final int ABYSSAL_GUARDIAN_11405 = 11405;
+ public static final int ABYSSAL_WALKER_11406 = 11406;
+ public static final int ABYSSAL_LEECH_11407 = 11407;
+ public static final int WEAK_CATALYTIC_GUARDIAN = 11408;
+ public static final int RICK_11409 = 11409;
+ public static final int RICK_11410 = 11410;
+ public static final int MEDIUM_CATALYTIC_GUARDIAN = 11411;
+ public static final int STRONG_CATALYTIC_GUARDIAN = 11412;
+ public static final int OVERCHARGED_CATALYTIC_GUARDIAN = 11413;
+ public static final int WEAK_ELEMENTAL_GUARDIAN = 11414;
+ public static final int MEDIUM_ELEMENTAL_GUARDIAN = 11415;
+ public static final int STRONG_ELEMENTAL_GUARDIAN = 11416;
+ public static final int OVERCHARGED_ELEMENTAL_GUARDIAN = 11417;
+ public static final int APPRENTICE_TAMARA = 11426;
+ public static final int APPRENTICE_CORDELIA = 11427;
+ public static final int GREATISH_GUARDIAN_11428 = 11428;
+ public static final int ABYSSAL_PROTECTOR_11429 = 11429;
+ public static final int BRIMSTAIL_11430 = 11430;
+ public static final int BRIMSTAIL_11431 = 11431;
+ public static final int ARCHMAGE_SEDRIDOR = 11432;
+ public static final int ARCHMAGE_SEDRIDOR_11433 = 11433;
+ public static final int AUBURY_11434 = 11434;
+ public static final int AUBURY_11435 = 11435;
+ public static final int WIZARD_PERSTEN = 11436;
+ public static final int WIZARD_PERSTEN_11437 = 11437;
+ public static final int WIZARD_PERSTEN_11438 = 11438;
+ public static final int WIZARD_PERSTEN_11439 = 11439;
+ public static final int APPRENTICE_TAMARA_11440 = 11440;
+ public static final int APPRENTICE_TAMARA_11441 = 11441;
+ public static final int APPRENTICE_TAMARA_11442 = 11442;
+ public static final int APPRENTICE_CORDELIA_11443 = 11443;
+ public static final int APPRENTICE_CORDELIA_11444 = 11444;
+ public static final int APPRENTICE_CORDELIA_11445 = 11445;
+ public static final int APPRENTICE_FELIX_11446 = 11446;
+ public static final int APPRENTICE_FELIX_11447 = 11447;
+ public static final int APPRENTICE_FELIX_11448 = 11448;
+ public static final int WIZARD_TRAIBORN_11449 = 11449;
+ public static final int ARCHMAGE_SEDRIDOR_11450 = 11450;
+ public static final int MYSTERIOUS_VOICE_11451 = 11451;
+ public static final int MYSTERIOUS_VOICE_11452 = 11452;
+ public static final int ABYSSAL_GUARDIAN_11453 = 11453;
+ public static final int ABYSSAL_WALKER_11454 = 11454;
+ public static final int THE_GREAT_GUARDIAN_11455 = 11455;
+ public static final int THE_GREAT_GUARDIAN_11456 = 11456;
/* This file is automatically generated. Do not edit. */
}
diff --git a/runelite-api/src/main/java/net/runelite/api/NullItemID.java b/runelite-api/src/main/java/net/runelite/api/NullItemID.java
index 4679c49e16..35eb01c8be 100644
--- a/runelite-api/src/main/java/net/runelite/api/NullItemID.java
+++ b/runelite-api/src/main/java/net/runelite/api/NullItemID.java
@@ -586,7 +586,6 @@ public final class NullItemID
public static final int NULL_1445 = 1445;
public static final int NULL_1447 = 1447;
public static final int NULL_1449 = 1449;
- public static final int NULL_1450 = 1450;
public static final int NULL_1451 = 1451;
public static final int NULL_1453 = 1453;
public static final int NULL_1455 = 1455;
@@ -2124,7 +2123,6 @@ public final class NullItemID
public static final int NULL_5544 = 5544;
public static final int NULL_5546 = 5546;
public static final int NULL_5548 = 5548;
- public static final int NULL_5549 = 5549;
public static final int NULL_5550 = 5550;
public static final int NULL_5551 = 5551;
public static final int NULL_5552 = 5552;
@@ -14043,5 +14041,65 @@ public final class NullItemID
public static final int NULL_26646 = 26646;
public static final int NULL_26648 = 26648;
public static final int NULL_26650 = 26650;
+ public static final int NULL_26783 = 26783;
+ public static final int NULL_26785 = 26785;
+ public static final int NULL_26787 = 26787;
+ public static final int NULL_26789 = 26789;
+ public static final int NULL_26790 = 26790;
+ public static final int NULL_26791 = 26791;
+ public static final int NULL_26793 = 26793;
+ public static final int NULL_26794 = 26794;
+ public static final int NULL_26795 = 26795;
+ public static final int NULL_26796 = 26796;
+ public static final int NULL_26797 = 26797;
+ public static final int NULL_26799 = 26799;
+ public static final int NULL_26800 = 26800;
+ public static final int NULL_26802 = 26802;
+ public static final int NULL_26803 = 26803;
+ public static final int NULL_26805 = 26805;
+ public static final int NULL_26806 = 26806;
+ public static final int NULL_26808 = 26808;
+ public static final int NULL_26810 = 26810;
+ public static final int NULL_26812 = 26812;
+ public static final int NULL_26814 = 26814;
+ public static final int NULL_26816 = 26816;
+ public static final int NULL_26817 = 26817;
+ public static final int NULL_26819 = 26819;
+ public static final int NULL_26821 = 26821;
+ public static final int NULL_26823 = 26823;
+ public static final int NULL_26825 = 26825;
+ public static final int NULL_26827 = 26827;
+ public static final int NULL_26829 = 26829;
+ public static final int NULL_26831 = 26831;
+ public static final int NULL_26833 = 26833;
+ public static final int NULL_26835 = 26835;
+ public static final int NULL_26837 = 26837;
+ public static final int NULL_26839 = 26839;
+ public static final int NULL_26841 = 26841;
+ public static final int NULL_26843 = 26843;
+ public static final int NULL_26845 = 26845;
+ public static final int NULL_26847 = 26847;
+ public static final int NULL_26849 = 26849;
+ public static final int NULL_26851 = 26851;
+ public static final int NULL_26853 = 26853;
+ public static final int NULL_26855 = 26855;
+ public static final int NULL_26857 = 26857;
+ public static final int NULL_26859 = 26859;
+ public static final int NULL_26861 = 26861;
+ public static final int NULL_26863 = 26863;
+ public static final int NULL_26865 = 26865;
+ public static final int NULL_26867 = 26867;
+ public static final int NULL_26869 = 26869;
+ public static final int NULL_26871 = 26871;
+ public static final int NULL_26873 = 26873;
+ public static final int NULL_26875 = 26875;
+ public static final int NULL_26877 = 26877;
+ public static final int NULL_26900 = 26900;
+ public static final int NULL_26902 = 26902;
+ public static final int NULL_26907 = 26907;
+ public static final int NULL_26909 = 26909;
+ public static final int NULL_26911 = 26911;
+ public static final int NULL_26913 = 26913;
+ public static final int NULL_26915 = 26915;
/* This file is automatically generated. Do not edit. */
}
diff --git a/runelite-api/src/main/java/net/runelite/api/NullNpcID.java b/runelite-api/src/main/java/net/runelite/api/NullNpcID.java
index 8b3a054c1f..061dbb4252 100644
--- a/runelite-api/src/main/java/net/runelite/api/NullNpcID.java
+++ b/runelite-api/src/main/java/net/runelite/api/NullNpcID.java
@@ -176,6 +176,7 @@ public final class NullNpcID
public static final int NULL_2780 = 2780;
public static final int NULL_2781 = 2781;
public static final int NULL_2831 = 2831;
+ public static final int NULL_2886 = 2886;
public static final int NULL_2934 = 2934;
public static final int NULL_2935 = 2935;
public static final int NULL_2936 = 2936;
@@ -211,6 +212,7 @@ public final class NullNpcID
public static final int NULL_3228 = 3228;
public static final int NULL_3229 = 3229;
public static final int NULL_3230 = 3230;
+ public static final int NULL_3248 = 3248;
public static final int NULL_3363 = 3363;
public static final int NULL_3365 = 3365;
public static final int NULL_3366 = 3366;
@@ -302,6 +304,7 @@ public final class NullNpcID
public static final int NULL_4785 = 4785;
public static final int NULL_4786 = 4786;
public static final int NULL_4815 = 4815;
+ public static final int NULL_4913 = 4913;
public static final int NULL_4939 = 4939;
public static final int NULL_4940 = 4940;
public static final int NULL_4941 = 4941;
@@ -326,6 +329,7 @@ public final class NullNpcID
public static final int NULL_4986 = 4986;
public static final int NULL_4988 = 4988;
public static final int NULL_5005 = 5005;
+ public static final int NULL_5034 = 5034;
public static final int NULL_5047 = 5047;
public static final int NULL_5049 = 5049;
public static final int NULL_5050 = 5050;
@@ -383,6 +387,7 @@ public final class NullNpcID
public static final int NULL_5902 = 5902;
public static final int NULL_5903 = 5903;
public static final int NULL_5930 = 5930;
+ public static final int NULL_5931 = 5931;
public static final int NULL_5953 = 5953;
public static final int NULL_6089 = 6089;
public static final int NULL_6090 = 6090;
@@ -1762,5 +1767,18 @@ public final class NullNpcID
public static final int NULL_11396 = 11396;
public static final int NULL_11397 = 11397;
public static final int NULL_11398 = 11398;
+ public static final int NULL_11418 = 11418;
+ public static final int NULL_11419 = 11419;
+ public static final int NULL_11420 = 11420;
+ public static final int NULL_11421 = 11421;
+ public static final int NULL_11422 = 11422;
+ public static final int NULL_11423 = 11423;
+ public static final int NULL_11424 = 11424;
+ public static final int NULL_11425 = 11425;
+ public static final int NULL_11457 = 11457;
+ public static final int NULL_11458 = 11458;
+ public static final int NULL_11459 = 11459;
+ public static final int NULL_11460 = 11460;
+ public static final int NULL_11461 = 11461;
/* This file is automatically generated. Do not edit. */
}
diff --git a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java
index dcb5736025..2ba2045f64 100644
--- a/runelite-api/src/main/java/net/runelite/api/NullObjectID.java
+++ b/runelite-api/src/main/java/net/runelite/api/NullObjectID.java
@@ -11912,6 +11912,7 @@ public final class NullObjectID
public static final int NULL_25372 = 25372;
public static final int NULL_25373 = 25373;
public static final int NULL_25375 = 25375;
+ public static final int NULL_25380 = 25380;
public static final int NULL_25382 = 25382;
public static final int NULL_25384 = 25384;
public static final int NULL_25394 = 25394;
@@ -18344,6 +18345,7 @@ public final class NullObjectID
public static final int NULL_38027 = 38027;
public static final int NULL_38028 = 38028;
public static final int NULL_38033 = 38033;
+ public static final int NULL_38044 = 38044;
public static final int NULL_38045 = 38045;
public static final int NULL_38046 = 38046;
public static final int NULL_38047 = 38047;
@@ -21428,6 +21430,201 @@ public final class NullObjectID
public static final int NULL_43465 = 43465;
public static final int NULL_43466 = 43466;
public static final int NULL_43467 = 43467;
+ public static final int NULL_43470 = 43470;
+ public static final int NULL_43471 = 43471;
+ public static final int NULL_43473 = 43473;
+ public static final int NULL_43480 = 43480;
+ public static final int NULL_43481 = 43481;
+ public static final int NULL_43482 = 43482;
+ public static final int NULL_43483 = 43483;
public static final int NULL_43486 = 43486;
+ public static final int NULL_43500 = 43500;
+ public static final int NULL_43501 = 43501;
+ public static final int NULL_43502 = 43502;
+ public static final int NULL_43505 = 43505;
+ public static final int NULL_43506 = 43506;
+ public static final int NULL_43507 = 43507;
+ public static final int NULL_43520 = 43520;
+ public static final int NULL_43521 = 43521;
+ public static final int NULL_43522 = 43522;
+ public static final int NULL_43523 = 43523;
+ public static final int NULL_43524 = 43524;
+ public static final int NULL_43525 = 43525;
+ public static final int NULL_43526 = 43526;
+ public static final int NULL_43527 = 43527;
+ public static final int NULL_43528 = 43528;
+ public static final int NULL_43529 = 43529;
+ public static final int NULL_43530 = 43530;
+ public static final int NULL_43531 = 43531;
+ public static final int NULL_43532 = 43532;
+ public static final int NULL_43533 = 43533;
+ public static final int NULL_43534 = 43534;
+ public static final int NULL_43536 = 43536;
+ public static final int NULL_43537 = 43537;
+ public static final int NULL_43538 = 43538;
+ public static final int NULL_43539 = 43539;
+ public static final int NULL_43540 = 43540;
+ public static final int NULL_43541 = 43541;
+ public static final int NULL_43542 = 43542;
+ public static final int NULL_43543 = 43543;
+ public static final int NULL_43544 = 43544;
+ public static final int NULL_43545 = 43545;
+ public static final int NULL_43546 = 43546;
+ public static final int NULL_43547 = 43547;
+ public static final int NULL_43548 = 43548;
+ public static final int NULL_43549 = 43549;
+ public static final int NULL_43550 = 43550;
+ public static final int NULL_43551 = 43551;
+ public static final int NULL_43552 = 43552;
+ public static final int NULL_43553 = 43553;
+ public static final int NULL_43554 = 43554;
+ public static final int NULL_43555 = 43555;
+ public static final int NULL_43556 = 43556;
+ public static final int NULL_43557 = 43557;
+ public static final int NULL_43558 = 43558;
+ public static final int NULL_43559 = 43559;
+ public static final int NULL_43560 = 43560;
+ public static final int NULL_43561 = 43561;
+ public static final int NULL_43562 = 43562;
+ public static final int NULL_43563 = 43563;
+ public static final int NULL_43564 = 43564;
+ public static final int NULL_43565 = 43565;
+ public static final int NULL_43566 = 43566;
+ public static final int NULL_43567 = 43567;
+ public static final int NULL_43568 = 43568;
+ public static final int NULL_43569 = 43569;
+ public static final int NULL_43570 = 43570;
+ public static final int NULL_43571 = 43571;
+ public static final int NULL_43572 = 43572;
+ public static final int NULL_43573 = 43573;
+ public static final int NULL_43574 = 43574;
+ public static final int NULL_43575 = 43575;
+ public static final int NULL_43576 = 43576;
+ public static final int NULL_43577 = 43577;
+ public static final int NULL_43578 = 43578;
+ public static final int NULL_43579 = 43579;
+ public static final int NULL_43580 = 43580;
+ public static final int NULL_43581 = 43581;
+ public static final int NULL_43582 = 43582;
+ public static final int NULL_43583 = 43583;
+ public static final int NULL_43584 = 43584;
+ public static final int NULL_43585 = 43585;
+ public static final int NULL_43586 = 43586;
+ public static final int NULL_43587 = 43587;
+ public static final int NULL_43588 = 43588;
+ public static final int NULL_43589 = 43589;
+ public static final int NULL_43590 = 43590;
+ public static final int NULL_43591 = 43591;
+ public static final int NULL_43592 = 43592;
+ public static final int NULL_43593 = 43593;
+ public static final int NULL_43594 = 43594;
+ public static final int NULL_43595 = 43595;
+ public static final int NULL_43596 = 43596;
+ public static final int NULL_43597 = 43597;
+ public static final int NULL_43598 = 43598;
+ public static final int NULL_43599 = 43599;
+ public static final int NULL_43600 = 43600;
+ public static final int NULL_43601 = 43601;
+ public static final int NULL_43602 = 43602;
+ public static final int NULL_43603 = 43603;
+ public static final int NULL_43604 = 43604;
+ public static final int NULL_43605 = 43605;
+ public static final int NULL_43606 = 43606;
+ public static final int NULL_43607 = 43607;
+ public static final int NULL_43608 = 43608;
+ public static final int NULL_43609 = 43609;
+ public static final int NULL_43610 = 43610;
+ public static final int NULL_43611 = 43611;
+ public static final int NULL_43612 = 43612;
+ public static final int NULL_43613 = 43613;
+ public static final int NULL_43614 = 43614;
+ public static final int NULL_43615 = 43615;
+ public static final int NULL_43616 = 43616;
+ public static final int NULL_43617 = 43617;
+ public static final int NULL_43618 = 43618;
+ public static final int NULL_43619 = 43619;
+ public static final int NULL_43620 = 43620;
+ public static final int NULL_43621 = 43621;
+ public static final int NULL_43622 = 43622;
+ public static final int NULL_43623 = 43623;
+ public static final int NULL_43624 = 43624;
+ public static final int NULL_43625 = 43625;
+ public static final int NULL_43626 = 43626;
+ public static final int NULL_43627 = 43627;
+ public static final int NULL_43628 = 43628;
+ public static final int NULL_43630 = 43630;
+ public static final int NULL_43631 = 43631;
+ public static final int NULL_43634 = 43634;
+ public static final int NULL_43637 = 43637;
+ public static final int NULL_43640 = 43640;
+ public static final int NULL_43643 = 43643;
+ public static final int NULL_43646 = 43646;
+ public static final int NULL_43649 = 43649;
+ public static final int NULL_43652 = 43652;
+ public static final int NULL_43655 = 43655;
+ public static final int NULL_43658 = 43658;
+ public static final int NULL_43659 = 43659;
+ public static final int NULL_43660 = 43660;
+ public static final int NULL_43661 = 43661;
+ public static final int NULL_43662 = 43662;
+ public static final int NULL_43663 = 43663;
+ public static final int NULL_43664 = 43664;
+ public static final int NULL_43665 = 43665;
+ public static final int NULL_43666 = 43666;
+ public static final int NULL_43667 = 43667;
+ public static final int NULL_43668 = 43668;
+ public static final int NULL_43669 = 43669;
+ public static final int NULL_43670 = 43670;
+ public static final int NULL_43671 = 43671;
+ public static final int NULL_43672 = 43672;
+ public static final int NULL_43673 = 43673;
+ public static final int NULL_43674 = 43674;
+ public static final int NULL_43678 = 43678;
+ public static final int NULL_43679 = 43679;
+ public static final int NULL_43680 = 43680;
+ public static final int NULL_43681 = 43681;
+ public static final int NULL_43682 = 43682;
+ public static final int NULL_43683 = 43683;
+ public static final int NULL_43684 = 43684;
+ public static final int NULL_43685 = 43685;
+ public static final int NULL_43686 = 43686;
+ public static final int NULL_43687 = 43687;
+ public static final int NULL_43688 = 43688;
+ public static final int NULL_43690 = 43690;
+ public static final int NULL_43691 = 43691;
+ public static final int NULL_43694 = 43694;
+ public static final int NULL_43725 = 43725;
+ public static final int NULL_43727 = 43727;
+ public static final int NULL_43728 = 43728;
+ public static final int NULL_43734 = 43734;
+ public static final int NULL_43735 = 43735;
+ public static final int NULL_43737 = 43737;
+ public static final int NULL_43781 = 43781;
+ public static final int NULL_43782 = 43782;
+ public static final int NULL_43783 = 43783;
+ public static final int NULL_43802 = 43802;
+ public static final int NULL_43823 = 43823;
+ public static final int NULL_43826 = 43826;
+ public static final int NULL_43828 = 43828;
+ public static final int NULL_43829 = 43829;
+ public static final int NULL_43830 = 43830;
+ public static final int NULL_43831 = 43831;
+ public static final int NULL_43832 = 43832;
+ public static final int NULL_43833 = 43833;
+ public static final int NULL_43834 = 43834;
+ public static final int NULL_43835 = 43835;
+ public static final int NULL_43836 = 43836;
+ public static final int NULL_43837 = 43837;
+ public static final int NULL_43838 = 43838;
+ public static final int NULL_43839 = 43839;
+ public static final int NULL_43840 = 43840;
+ public static final int NULL_43841 = 43841;
+ public static final int NULL_43842 = 43842;
+ public static final int NULL_43843 = 43843;
+ public static final int NULL_43844 = 43844;
+ public static final int NULL_43845 = 43845;
+ public static final int NULL_43846 = 43846;
+ public static final int NULL_43847 = 43847;
+ public static final int NULL_43848 = 43848;
/* This file is automatically generated. Do not edit. */
}
diff --git a/runelite-api/src/main/java/net/runelite/api/ObjectID.java b/runelite-api/src/main/java/net/runelite/api/ObjectID.java
index 872014c641..865e37b59a 100644
--- a/runelite-api/src/main/java/net/runelite/api/ObjectID.java
+++ b/runelite-api/src/main/java/net/runelite/api/ObjectID.java
@@ -526,7 +526,7 @@ public final class ObjectID
public static final int CHARMS = 907;
public static final int MAGICAL_SYMBOL = 908;
public static final int PLAQUE = 909;
- public static final int EVIL_EYE_DECORATION = 910;
+ public static final int EYE_DECORATION = 910;
public static final int GLYPHS = 911;
public static final int FONT = 915;
public static final int DOOR_954 = 954;
@@ -13471,7 +13471,6 @@ public final class ObjectID
public static final int SOUL_RIFT = 25377;
public static final int AIR_RIFT = 25378;
public static final int MIND_RIFT = 25379;
- public static final int BLOOD_RIFT = 25380;
public static final int PASSAGE_25381 = 25381;
public static final int BLOCKAGE = 25383;
public static final int CHEST_25385 = 25385;
@@ -15783,7 +15782,7 @@ public final class ObjectID
public static final int MOUNTED_MAX_CAPE_29625 = 29625;
public static final int CRACK_29626 = 29626;
public static final int CRACK_29627 = 29627;
- public static final int RUNECRAFTING_ALTAR = 29631;
+ public static final int ALTAR_29631 = 29631;
public static final int LADDER_29635 = 29635;
public static final int LADDER_29636 = 29636;
public static final int CLAN_WARS_PORTAL = 29667;
@@ -19687,7 +19686,6 @@ public final class ObjectID
public static final int RAISED_COFFIN = 38041;
public static final int GRAVESTONE_38042 = 38042;
public static final int GRAVESTONE_38043 = 38043;
- public static final int MYSTERIOUS_RUINS_38044 = 38044;
public static final int GRAVE_38049 = 38049;
public static final int GRAVESTONE_38050 = 38050;
public static final int GRAVESTONE_38051 = 38051;
@@ -22025,23 +22023,190 @@ public final class ObjectID
public static final int LARGE_DOOR_43459 = 43459;
public static final int LARGE_DOOR_43460 = 43460;
public static final int CAVE_ENTRANCE_43462 = 43462;
- public static final int BANNER_43468 = 43468;
- public static final int BANNER_43469 = 43469;
- public static final int BANNER_43470 = 43470;
- public static final int BANNER_43471 = 43471;
- public static final int PARTY_BALLOONS = 43472;
- public static final int PARTY_BALLOONS_43473 = 43473;
- public static final int PARTY_BALLOONS_43474 = 43474;
- public static final int PARTY_BALLOONS_43475 = 43475;
- public static final int PARTY_BALLOONS_43476 = 43476;
- public static final int SINK_43477 = 43477;
- public static final int BARREL_OF_FLOUR_43478 = 43478;
- public static final int CLAY_OVEN_43479 = 43479;
- public static final int COOKING_SHELF_UTENSILS = 43480;
- public static final int JUDGES_TABLE = 43481;
- public static final int TABLE_43482 = 43482;
- public static final int CUPBOARD_43483 = 43483;
- public static final int LOOT_CHEST = 43484;
+ public static final int LOOT_CHEST = 43468;
+ public static final int LOOT_CHEST_43469 = 43469;
+ public static final int ANCIENT_BRAZIER_43472 = 43472;
+ public static final int ANCIENT_BRAZIER_43474 = 43474;
+ public static final int FIRE_43475 = 43475;
+ public static final int MYSTERIOUS_RUINS_43476 = 43476;
+ public static final int MYSTERIOUS_RUINS_43477 = 43477;
+ public static final int PORTAL_43478 = 43478;
+ public static final int ALTAR_43479 = 43479;
+ public static final int LOOT_CHEST_43484 = 43484;
public static final int LOOT_CHEST_43485 = 43485;
+ public static final int GROUP_STORAGE = 43487;
+ public static final int GROUP_STORAGE_43488 = 43488;
+ public static final int GROUP_STORAGE_43489 = 43489;
+ public static final int GROUP_STORAGE_43490 = 43490;
+ public static final int GROUP_STORAGE_43491 = 43491;
+ public static final int GROUP_STORAGE_43492 = 43492;
+ public static final int GROUP_STORAGE_43493 = 43493;
+ public static final int GROUP_STORAGE_43494 = 43494;
+ public static final int GROUP_STORAGE_43495 = 43495;
+ public static final int GROUP_STORAGE_43496 = 43496;
+ public static final int GROUP_STORAGE_43497 = 43497;
+ public static final int GROUP_STORAGE_43498 = 43498;
+ public static final int GROUP_STORAGE_43499 = 43499;
+ public static final int RAIN = 43503;
+ public static final int RAIN_43504 = 43504;
+ public static final int SKELETON_43508 = 43508;
+ public static final int PILLAR_43509 = 43509;
+ public static final int PILLAR_43510 = 43510;
+ public static final int PILLAR_43511 = 43511;
+ public static final int RUINED_PILLAR_43512 = 43512;
+ public static final int RUINED_PILLAR_43513 = 43513;
+ public static final int PILLAR_43514 = 43514;
+ public static final int RUINED_PILLAR_43515 = 43515;
+ public static final int PILLAR_43516 = 43516;
+ public static final int RUBBLE_43517 = 43517;
+ public static final int RUBBLE_43518 = 43518;
+ public static final int RUBBLE_43519 = 43519;
+ public static final int CART_43535 = 43535;
+ public static final int WHALEFALL = 43629;
+ public static final int ELK_KELP = 43632;
+ public static final int ELK_KELP_43633 = 43633;
+ public static final int DARK_LACE = 43635;
+ public static final int DARK_LACE_43636 = 43636;
+ public static final int ELK_KELP_43638 = 43638;
+ public static final int ELK_KELP_43639 = 43639;
+ public static final int ELK_KELP_43641 = 43641;
+ public static final int ELK_KELP_43642 = 43642;
+ public static final int DARK_LACE_43644 = 43644;
+ public static final int DARK_LACE_43645 = 43645;
+ public static final int ELK_KELP_43647 = 43647;
+ public static final int ELK_KELP_43648 = 43648;
+ public static final int ELK_KELP_43650 = 43650;
+ public static final int ELK_KELP_43651 = 43651;
+ public static final int DARK_LACE_43653 = 43653;
+ public static final int DARK_LACE_43654 = 43654;
+ public static final int ELK_KELP_43656 = 43656;
+ public static final int ELK_KELP_43657 = 43657;
+ public static final int PINEAPPLE = 43675;
+ public static final int HEAD = 43676;
+ public static final int ROCK_43677 = 43677;
+ public static final int FOUNTAIN_43689 = 43689;
+ public static final int PORTAL_43692 = 43692;
+ public static final int PORTAL_43693 = 43693;
+ public static final int REWARDS_GUARDIAN = 43695;
+ public static final int DEPOSIT_POOL = 43696;
+ public static final int BANK_CHEST_43697 = 43697;
+ public static final int STATUE_43698 = 43698;
+ public static final int STATUE_43699 = 43699;
+ public static final int BARRIER_43700 = 43700;
+ public static final int GUARDIAN_OF_AIR = 43701;
+ public static final int GUARDIAN_OF_WATER = 43702;
+ public static final int GUARDIAN_OF_EARTH = 43703;
+ public static final int GUARDIAN_OF_FIRE = 43704;
+ public static final int GUARDIAN_OF_MIND = 43705;
+ public static final int GUARDIAN_OF_CHAOS = 43706;
+ public static final int GUARDIAN_OF_DEATH = 43707;
+ public static final int GUARDIAN_OF_BLOOD = 43708;
+ public static final int GUARDIAN_OF_BODY = 43709;
+ public static final int GUARDIAN_OF_COSMIC = 43710;
+ public static final int GUARDIAN_OF_NATURE = 43711;
+ public static final int GUARDIAN_OF_LAW = 43712;
+ public static final int ABYSSAL_RIFT_43713 = 43713;
+ public static final int ABYSSAL_RIFT_43714 = 43714;
+ public static final int GUARDIAN_PARTS = 43715;
+ public static final int GUARDIAN_PARTS_43716 = 43716;
+ public static final int GUARDIAN_REMAINS = 43717;
+ public static final int GUARDIAN_REMAINS_43718 = 43718;
+ public static final int LARGE_GUARDIAN_REMAINS = 43719;
+ public static final int HUGE_GUARDIAN_REMAINS = 43720;
+ public static final int FALLEN_GUARDIAN = 43721;
+ public static final int ESSENCE_PILE_ELEMENTAL = 43722;
+ public static final int ESSENCE_PILE_CATALYTIC = 43723;
+ public static final int RUBBLE_43724 = 43724;
+ public static final int RUBBLE_43726 = 43726;
+ public static final int PORTAL_43729 = 43729;
+ public static final int PORTAL_43730 = 43730;
+ public static final int UNCHARGED_CELLS = 43731;
+ public static final int UNCHARGED_CELLS_43732 = 43732;
+ public static final int WEAK_CELLS = 43733;
+ public static final int CELL_TILE_BROKEN = 43736;
+ public static final int INACTIVE_CELL_TILE = 43738;
+ public static final int INACTIVE_CELL_TILE_43739 = 43739;
+ public static final int WEAK_CELL_TILE = 43740;
+ public static final int MEDIUM_CELL_TILE = 43741;
+ public static final int STRONG_CELL_TILE = 43742;
+ public static final int OVERPOWERED_CELL_TILE = 43743;
+ public static final int WEAK_BARRIER = 43744;
+ public static final int WEAK_BARRIER_43745 = 43745;
+ public static final int MEDIUM_BARRIER = 43746;
+ public static final int MEDIUM_BARRIER_43747 = 43747;
+ public static final int STRONG_BARRIER = 43748;
+ public static final int STRONG_BARRIER_43749 = 43749;
+ public static final int OVERCHARGED_BARRIER = 43750;
+ public static final int OVERCHARGED_BARRIER_43751 = 43751;
+ public static final int ELEMENTAL_GUIDE = 43752;
+ public static final int CATALYTIC_GUIDE = 43753;
+ public static final int WORKBENCH_43754 = 43754;
+ public static final int CAVE_43755 = 43755;
+ public static final int CAVE_43756 = 43756;
+ public static final int CAVE_43757 = 43757;
+ public static final int CAVE_43758 = 43758;
+ public static final int CAVE_43759 = 43759;
+ public static final int STRANGE_WALL_43760 = 43760;
+ public static final int CAVE_43761 = 43761;
+ public static final int CAVE_43762 = 43762;
+ public static final int CAVE_43763 = 43763;
+ public static final int LADDER_43764 = 43764;
+ public static final int PORTAL_43765 = 43765;
+ public static final int STOOL_43766 = 43766;
+ public static final int PORTAL_43767 = 43767;
+ public static final int EARTH_ENERGY = 43768;
+ public static final int COSMIC_ENERGY = 43769;
+ public static final int DEATH_ENERGY = 43770;
+ public static final int NATURE_ENERGY = 43771;
+ public static final int LAW_ENERGY = 43772;
+ public static final int FIRE_ENERGY = 43773;
+ public static final int EARTH_ENERGY_43774 = 43774;
+ public static final int COSMIC_ENERGY_43775 = 43775;
+ public static final int DEATH_ENERGY_43776 = 43776;
+ public static final int NATURE_ENERGY_43777 = 43777;
+ public static final int LAW_ENERGY_43778 = 43778;
+ public static final int FIRE_ENERGY_43779 = 43779;
+ public static final int MYSTERIOUS_STONE_43780 = 43780;
+ public static final int STATUE_43784 = 43784;
+ public static final int STATUE_43785 = 43785;
+ public static final int STATUE_43786 = 43786;
+ public static final int STATUE_43787 = 43787;
+ public static final int STATUE_43788 = 43788;
+ public static final int STATUE_43789 = 43789;
+ public static final int STATUE_43790 = 43790;
+ public static final int STATUE_43791 = 43791;
+ public static final int STATUE_43792 = 43792;
+ public static final int STATUE_43793 = 43793;
+ public static final int STATUE_43794 = 43794;
+ public static final int STATUE_43795 = 43795;
+ public static final int GUARDIAN_REMAINS_43796 = 43796;
+ public static final int GUARDIAN_REMAINS_43797 = 43797;
+ public static final int GUARDIAN_REMAINS_43798 = 43798;
+ public static final int GUARDIAN_REMAINS_43799 = 43799;
+ public static final int GUARDIAN_REMAINS_43800 = 43800;
+ public static final int GUARDIAN_REMAINS_43801 = 43801;
+ public static final int RUBBLE_43803 = 43803;
+ public static final int GUARDIAN_REMAINS_43804 = 43804;
+ public static final int GUARDIAN_REMAINS_43805 = 43805;
+ public static final int TABLE_43806 = 43806;
+ public static final int TABLE_43807 = 43807;
+ public static final int TABLE_43808 = 43808;
+ public static final int GUARDIAN_OF_AIR_43809 = 43809;
+ public static final int GUARDIAN_OF_WATER_43810 = 43810;
+ public static final int GUARDIAN_OF_EARTH_43811 = 43811;
+ public static final int GUARDIAN_OF_FIRE_43812 = 43812;
+ public static final int GUARDIAN_OF_MIND_43813 = 43813;
+ public static final int GUARDIAN_OF_CHAOS_43814 = 43814;
+ public static final int GUARDIAN_OF_DEATH_43815 = 43815;
+ public static final int GUARDIAN_OF_BLOOD_43816 = 43816;
+ public static final int GUARDIAN_OF_BODY_43817 = 43817;
+ public static final int GUARDIAN_OF_COSMIC_43818 = 43818;
+ public static final int GUARDIAN_OF_NATURE_43819 = 43819;
+ public static final int GUARDIAN_OF_LAW_43820 = 43820;
+ public static final int GUARDIAN_OF_WATER_43821 = 43821;
+ public static final int GUARDIAN_OF_MIND_43822 = 43822;
+ public static final int BLOOD_RIFT = 43824;
+ public static final int BLOOD_RIFT_43825 = 43825;
+ public static final int PLANT_43827 = 43827;
/* This file is automatically generated. Do not edit. */
}
diff --git a/runelite-api/src/main/java/net/runelite/api/Quest.java b/runelite-api/src/main/java/net/runelite/api/Quest.java
index d5e316bc00..e32c60ef0f 100644
--- a/runelite-api/src/main/java/net/runelite/api/Quest.java
+++ b/runelite-api/src/main/java/net/runelite/api/Quest.java
@@ -30,7 +30,6 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum Quest
{
- //Free Quests
BLACK_KNIGHTS_FORTRESS(299, "Black Knights' Fortress"),
COOKS_ASSISTANT(300, "Cook's Assistant"),
THE_CORSAIR_CURSE(301, "The Corsair Curse"),
@@ -53,8 +52,6 @@ public enum Quest
WITCHS_POTION(318, "Witch's Potion"),
X_MARKS_THE_SPOT(3155, "X Marks the Spot"),
BELOW_ICE_MOUNTAIN(2874, "Below Ice Mountain"),
-
- //Members' Quests
ANIMAL_MAGNETISM(331, "Animal Magnetism"),
ANOTHER_SLICE_OF_HAM(332, "Another Slice of H.A.M."),
BETWEEN_A_ROCK(333, "Between a Rock..."),
@@ -184,8 +181,6 @@ public enum Quest
A_KINGDOM_DIVIDED(2971, "A Kingdom Divided"),
A_NIGHT_AT_THE_THEATRE(949, "A Night at the Theatre"),
LAND_OF_THE_GOBLINS(4135, "Land of the Goblins"),
-
- //Miniquests
ENTER_THE_ABYSS(3140, "Enter the Abyss"),
ARCHITECTURAL_ALLIANCE(320, "Architectural Alliance"),
BEAR_YOUR_SOUL(1275, "Bear Your Soul"),
@@ -202,7 +197,8 @@ public enum Quest
DADDYS_HOME(1688, "Daddy's Home"),
THE_FROZEN_DOOR(3768, "The Frozen Door"),
HOPESPEARS_WILL(4136, "Hopespear's Will"),
-;
+ TEMPLE_OF_THE_EYE(4273, "Temple of the Eye"),
+ ;
@Getter
private final int id;
diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java
index aafe123a0f..bf63a54f59 100644
--- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java
+++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java
@@ -275,12 +275,6 @@ public final class ScriptID
@ScriptArguments(integer = 3)
public static final int GE_ITEM_SEARCH = 752;
- /**
- * Builds the quest list inside the quest tab that shows each quest's progress
- */
- @ScriptArguments(integer = 3)
- public static final int QUESTLIST_PROGRESS_LIST_SHOW = 1354;
-
/**
* Called when the friends list is updated
*
diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java
index 617f5be107..938be8c9d9 100644
--- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java
+++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java
@@ -132,7 +132,6 @@ public final class WidgetID
public static final int SKOTIZO_GROUP_ID = 308;
public static final int ENTERING_HOUSE_GROUP_ID = 71;
public static final int FULLSCREEN_CONTAINER_TLI = 165;
- public static final int QUESTLIST_GROUP_ID = 399;
public static final int SKILLS_GROUP_ID = 320;
public static final int MUSIC_GROUP_ID = 239;
public static final int BARROWS_PUZZLE_GROUP_ID = 25;
@@ -890,16 +889,6 @@ public final class WidgetID
static final int CONTAINER = 2;
}
- static class QuestList
- {
- static final int BOX = 0;
- static final int SCROLLBAR = 4;
- static final int CONTAINER = 5;
- static final int FREE_CONTAINER = 6;
- static final int MEMBERS_CONTAINER = 7;
- static final int MINIQUEST_CONTAINER = 8;
- }
-
static class Music
{
static final int CONTAINER = 0;
diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java
index 1a358475f1..7d68c7c5c3 100644
--- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java
+++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java
@@ -521,13 +521,6 @@ public enum WidgetInfo
SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER),
- QUESTLIST_BOX(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.BOX),
- QUESTLIST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.CONTAINER),
- QUESTLIST_SCROLLBAR(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.SCROLLBAR),
- QUESTLIST_FREE_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.FREE_CONTAINER),
- QUESTLIST_MEMBERS_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MEMBERS_CONTAINER),
- QUESTLIST_MINIQUEST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MINIQUEST_CONTAINER),
-
SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER),
SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER),
SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/Pet.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/Pet.java
index 2583be2d22..712fc5b2b7 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/Pet.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/Pet.java
@@ -80,7 +80,9 @@ enum Pet
LITTLE_NIGHTMARE("Little nightmare", ItemID.LITTLE_NIGHTMARE),
LIL_CREATOR("Lil' creator", ItemID.LIL_CREATOR),
TINY_TEMPOR("Tiny tempor", ItemID.TINY_TEMPOR),
- NEXLING("Nexling", ItemID.NEXLING);
+ NEXLING("Nexling", ItemID.NEXLING),
+ ABYSSAL_PROTECTOR("Abyssal protector", ItemID.ABYSSAL_PROTECTOR),
+ ;
private final String name;
private final Integer iconID;
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java
index f2f552ad68..028940f714 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java
@@ -116,7 +116,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", "Fishing trawler", null, new WorldPoint(2676, 3169, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
new EmoteClue("Panic in the heart of the Haunted Woods. Beware of double agents! Have no items equipped when you do.", "Haunted Woods (ALQ)", null, new WorldPoint(3611, 3492, 0), DOUBLE_AGENT_108, PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
new EmoteClue("Show your anger towards the Statue of Saradomin in Ellamaria's garden. Beware of double agents! Equip a zamorak godsword.", "Varrock Castle", BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS, new WorldPoint(3230, 3478, 0), DOUBLE_AGENT_141, ANGRY, any("Zamorak godsword", item(ZAMORAK_GODSWORD), item(ZAMORAK_GODSWORD_OR))),
- new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", "Draynor Village", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), DOUBLE_AGENT_141, ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)),
+ new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", "Draynor Village", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), DOUBLE_AGENT_141, ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP), item(ABYSSAL_WHIP_OR)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)),
new EmoteClue("Beckon by a collection of crystalline maple trees. Beware of double agents! Equip Bryophyta's staff and a nature tiara.", "North of Prifddinas", CRYSTALLINE_MAPLE_TREES, new WorldPoint(2211, 3427, 0), DOUBLE_AGENT_141, BECKON, range("Bryophyta's staff", BRYOPHYTAS_STAFF_UNCHARGED, BRYOPHYTAS_STAFF), item(NATURE_TIARA)),
new EmoteClue("Beckon in the Digsite, near the eastern winch. Bow before you talk to me. Equip a green gnome hat, snakeskin boots and an iron pickaxe.", "Digsite", DIGSITE, new WorldPoint(3370, 3425, 0), BECKON, BOW, item(GREEN_HAT), item(SNAKESKIN_BOOTS), item(IRON_PICKAXE)),
new EmoteClue("Beckon in Tai Bwo Wannai. Clap before you talk to me. Equip green dragonhide chaps, a ring of dueling and a mithril medium helmet.", "Tai Bwo Wannai", SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE, new WorldPoint(2803, 3073, 0), BECKON, CLAP, item(GREEN_DHIDE_CHAPS), any("Ring of dueling", item(RING_OF_DUELING1), item(RING_OF_DUELING2), item(RING_OF_DUELING3), item(RING_OF_DUELING4), item(RING_OF_DUELING5), item(RING_OF_DUELING6), item(RING_OF_DUELING7), item(RING_OF_DUELING8)), item(MITHRIL_MED_HELM)),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java
index aaf8006d5a..01c34a68c6 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java
@@ -203,7 +203,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam
new SkillChallengeClue("Activate the Chivalry prayer."),
new SkillChallengeClue("Hand in a Tier 2 or higher set of Shayzien supply armour. (Requires 11 lovakite bars)", "take the lovakengj armourers a boxed set of shayzien supply armour at tier 2 or above.", any("Shayzien Supply Set (Tier 2 or higher)", item(ItemID.SHAYZIEN_SUPPLY_SET_2), item(ItemID.SHAYZIEN_SUPPLY_SET_3), item(ItemID.SHAYZIEN_SUPPLY_SET_4), item(ItemID.SHAYZIEN_SUPPLY_SET_5))),
// Master Sherlock Tasks
- new SkillChallengeClue("Equip an abyssal whip in front of the abyssal demons of the Slayer Tower.", true, any("Abyssal Whip", item(ItemID.ABYSSAL_WHIP), item(ItemID.FROZEN_ABYSSAL_WHIP), item(ItemID.VOLCANIC_ABYSSAL_WHIP))),
+ new SkillChallengeClue("Equip an abyssal whip in front of the abyssal demons of the Slayer Tower.", true, any("Abyssal Whip", item(ItemID.ABYSSAL_WHIP), item(ItemID.FROZEN_ABYSSAL_WHIP), item(ItemID.VOLCANIC_ABYSSAL_WHIP), item(ItemID.ABYSSAL_WHIP_OR))),
new SkillChallengeClue("Smith a runite med helm.", ANY_HAMMER, item(ItemID.RUNITE_BAR)),
new SkillChallengeClue("Teleport to a spirit tree you planted yourself."),
new SkillChallengeClue("Create a Barrows teleport tablet.", item(ItemID.DARK_ESSENCE_BLOCK), xOfItem(ItemID.BLOOD_RUNE, 1), xOfItem(ItemID.LAW_RUNE, 2), xOfItem(ItemID.SOUL_RUNE, 2)),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
index 9f80cf6023..1c30e53246 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
@@ -355,6 +355,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
System.setProperty("jogl.debug", "true");
}
+ System.setProperty("jogamp.gluegen.TestTempDirExec", "false");
+
GLProfile.initSingleton();
invokeOnMainThread(() ->
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java
index 1031765645..a4eea6a780 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/grounditems/GroundItemsConfig.java
@@ -46,8 +46,7 @@ public interface GroundItemsConfig extends Config
@ConfigSection(
name = "Item Lists",
description = "The highlighted and hidden item lists",
- position = 0,
- closedByDefault = true
+ position = 0
)
String itemLists = "itemLists";
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java
index aa723dc8a7..793b357fde 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018, Psikoi
- * Copyright (c) 2018, Tomas Slusny
+ * Copyright (c) 2018, Adam
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,682 +25,1478 @@
*/
package net.runelite.client.plugins.loottracker;
-import static com.google.common.collect.Iterables.concat;
-import com.google.common.collect.Lists;
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.GridLayout;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Multisets;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.inject.Provides;
import java.awt.image.BufferedImage;
-import java.util.ArrayDeque;
+import java.io.IOException;
+import java.time.Duration;
+import java.time.Instant;
+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.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
-import java.util.function.Predicate;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import javax.swing.BorderFactory;
-import javax.swing.BoxLayout;
-import javax.swing.ButtonGroup;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JMenuItem;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButton;
-import javax.swing.JToggleButton;
-import javax.swing.border.EmptyBorder;
-import javax.swing.plaf.basic.BasicButtonUI;
-import javax.swing.plaf.basic.BasicToggleButtonUI;
+import javax.swing.SwingUtilities;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+import net.runelite.api.ChatMessageType;
+import net.runelite.api.Client;
+import net.runelite.api.GameState;
+import net.runelite.api.InventoryID;
+import net.runelite.api.ItemComposition;
+import net.runelite.api.ItemContainer;
+import net.runelite.api.ItemID;
+import net.runelite.api.MenuAction;
+import net.runelite.api.MessageNode;
+import net.runelite.api.NPC;
+import net.runelite.api.ObjectID;
+import net.runelite.api.Player;
+import net.runelite.api.Skill;
+import net.runelite.api.SpriteID;
+import net.runelite.api.WorldType;
+import net.runelite.api.coords.WorldPoint;
+import net.runelite.api.events.ChatMessage;
+import net.runelite.api.events.CommandExecuted;
+import net.runelite.api.events.GameStateChanged;
+import net.runelite.api.events.ItemContainerChanged;
+import net.runelite.api.events.MenuOptionClicked;
+import net.runelite.api.events.WidgetLoaded;
+import net.runelite.api.widgets.WidgetID;
+import net.runelite.client.account.AccountSession;
+import net.runelite.client.account.SessionManager;
+import net.runelite.client.callback.ClientThread;
+import net.runelite.client.chat.ChatColorType;
+import net.runelite.client.chat.ChatMessageBuilder;
+import net.runelite.client.chat.ChatMessageManager;
+import net.runelite.client.chat.QueuedMessage;
+import net.runelite.client.config.ConfigManager;
+import net.runelite.client.eventbus.EventBus;
+import net.runelite.client.eventbus.Subscribe;
+import net.runelite.client.events.ClientShutdown;
+import net.runelite.client.events.ConfigChanged;
+import net.runelite.client.events.NpcLootReceived;
+import net.runelite.client.events.PlayerLootReceived;
+import net.runelite.client.events.RuneScapeProfileChanged;
+import net.runelite.client.events.SessionClose;
+import net.runelite.client.events.SessionOpen;
import net.runelite.client.game.ItemManager;
-import net.runelite.client.ui.ColorScheme;
-import net.runelite.client.ui.FontManager;
-import net.runelite.client.ui.PluginPanel;
-import net.runelite.client.ui.components.PluginErrorPanel;
-import net.runelite.client.util.ColorUtil;
+import net.runelite.client.game.ItemStack;
+import net.runelite.client.game.LootManager;
+import net.runelite.client.game.SpriteManager;
+import net.runelite.client.plugins.Plugin;
+import net.runelite.client.plugins.PluginDescriptor;
+import net.runelite.client.task.Schedule;
+import net.runelite.client.ui.ClientToolbar;
+import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.QuantityFormatter;
-import net.runelite.client.util.SwingUtil;
+import net.runelite.client.util.Text;
+import net.runelite.http.api.loottracker.GameItem;
+import net.runelite.http.api.loottracker.LootAggregate;
+import net.runelite.http.api.loottracker.LootRecord;
import net.runelite.http.api.loottracker.LootRecordType;
+import org.apache.commons.text.WordUtils;
-class LootTrackerPanel extends PluginPanel
+@PluginDescriptor(
+ name = "Loot Tracker",
+ description = "Tracks loot from monsters and minigames",
+ tags = {"drops"}
+)
+@Slf4j
+public class LootTrackerPlugin extends Plugin
{
- private static final int MAX_LOOT_BOXES = 500;
+ private static final int MAX_DROPS = 1024;
+ private static final Duration MAX_AGE = Duration.ofDays(365L);
- private static final ImageIcon SINGLE_LOOT_VIEW;
- private static final ImageIcon SINGLE_LOOT_VIEW_FADED;
- private static final ImageIcon SINGLE_LOOT_VIEW_HOVER;
- private static final ImageIcon GROUPED_LOOT_VIEW;
- private static final ImageIcon GROUPED_LOOT_VIEW_FADED;
- private static final ImageIcon GROUPED_LOOT_VIEW_HOVER;
- private static final ImageIcon BACK_ARROW_ICON;
- private static final ImageIcon BACK_ARROW_ICON_HOVER;
- private static final ImageIcon VISIBLE_ICON;
- private static final ImageIcon VISIBLE_ICON_HOVER;
- private static final ImageIcon INVISIBLE_ICON;
- private static final ImageIcon INVISIBLE_ICON_HOVER;
- private static final ImageIcon COLLAPSE_ICON;
- private static final ImageIcon EXPAND_ICON;
+ // Activity/Event loot handling
+ private static final Pattern CLUE_SCROLL_PATTERN = Pattern.compile("You have completed [0-9]+ ([a-z]+) Treasure Trails?\\.");
+ private static final int THEATRE_OF_BLOOD_REGION = 12867;
+ private static final int THEATRE_OF_BLOOD_LOBBY = 14642;
- private static final String HTML_LABEL_TEMPLATE =
- "%s%s";
- private static final String RESET_ALL_WARNING_TEXT =
- "This will permanently delete all loot.";
- private static final String RESET_CURRENT_WARNING_TEXT =
- "This will permanently delete \"%s\" loot.";
- private static final String RESET_ONE_WARNING_TEXT =
- "This will delete one kill.";
+ // Herbiboar loot handling
+ @VisibleForTesting
+ static final String HERBIBOAR_LOOTED_MESSAGE = "You harvest herbs from the herbiboar, whereupon it escapes.";
+ private static final String HERBIBOAR_EVENT = "Herbiboar";
+ private static final Pattern HERBIBOAR_HERB_SACK_PATTERN = Pattern.compile(".+(Grimy .+?) herb.+");
- // When there is no loot, display this
- private final PluginErrorPanel errorPanel = new PluginErrorPanel();
+ // Seed Pack loot handling
+ private static final String SEEDPACK_EVENT = "Seed pack";
- // Handle loot boxes
- private final JPanel logsContainer = new JPanel();
+ // Hespori loot handling
+ private static final String HESPORI_LOOTED_MESSAGE = "You have successfully cleared this patch for new crops.";
+ private static final String HESPORI_EVENT = "Hespori";
+ private static final int HESPORI_REGION = 5021;
- // Handle overall session data
- private final JPanel overallPanel;
- private final JLabel overallKillsLabel = new JLabel();
- private final JLabel overallGpLabel = new JLabel();
- private final JLabel overallIcon = new JLabel();
+ // Chest loot handling
+ private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!";
+ private static final Pattern ROGUES_CHEST_PATTERN = Pattern.compile("You find (a|some)([a-z\\s]*) inside.");
+ private static final Pattern LARRAN_LOOTED_PATTERN = Pattern.compile("You have opened Larran's (big|small) chest .*");
+ // Used by Stone Chest, Isle of Souls chest, Dark Chest
+ private static final String OTHER_CHEST_LOOTED_MESSAGE = "You steal some loot from the chest.";
+ private static final String DORGESH_KAAN_CHEST_LOOTED_MESSAGE = "You find treasure inside!";
+ private static final String GRUBBY_CHEST_LOOTED_MESSAGE = "You have opened the Grubby Chest";
+ private static final Pattern HAM_CHEST_LOOTED_PATTERN = Pattern.compile("Your (?[a-z]+) key breaks in the lock.*");
+ private static final int HAM_STOREROOM_REGION = 10321;
+ private static final Map CHEST_EVENT_TYPES = new ImmutableMap.Builder().
+ put(5179, "Brimstone Chest").
+ put(11573, "Crystal Chest").
+ put(12093, "Larran's big chest").
+ put(12127, "The Gauntlet").
+ put(13113, "Larran's small chest").
+ put(13151, "Elven Crystal Chest").
+ put(5277, "Stone chest").
+ put(10835, "Dorgesh-Kaan Chest").
+ put(10834, "Dorgesh-Kaan Chest").
+ put(7323, "Grubby Chest").
+ put(8593, "Isle of Souls Chest").
+ put(7827, "Dark Chest").
+ put(13117, "Rogues' Chest").
+ build();
- // Details and navigation
- private final JPanel actionsPanel;
- private final JLabel detailsTitle = new JLabel();
- private final JButton backBtn = new JButton();
- private final JToggleButton viewHiddenBtn = new JToggleButton();
- private final JRadioButton singleLootBtn = new JRadioButton();
- private final JRadioButton groupedLootBtn = new JRadioButton();
- private final JButton collapseBtn = new JButton();
+ // Shade chest loot handling
+ private static final Pattern SHADE_CHEST_NO_KEY_PATTERN = Pattern.compile("You need a [a-z]+ key with a [a-z]+ trim to open this chest .*");
+ private static final Map SHADE_CHEST_OBJECTS = new ImmutableMap.Builder().
+ put(ObjectID.BRONZE_CHEST, "Bronze key red").
+ put(ObjectID.BRONZE_CHEST_4112, "Bronze key brown").
+ put(ObjectID.BRONZE_CHEST_4113, "Bronze key crimson").
+ put(ObjectID.BRONZE_CHEST_4114, "Bronze key black").
+ put(ObjectID.BRONZE_CHEST_4115, "Bronze key purple").
+ put(ObjectID.STEEL_CHEST, "Steel key red").
+ put(ObjectID.STEEL_CHEST_4117, "Steel key brown").
+ put(ObjectID.STEEL_CHEST_4118, "Steel key crimson").
+ put(ObjectID.STEEL_CHEST_4119, "Steel key black").
+ put(ObjectID.STEEL_CHEST_4120, "Steel key purple").
+ put(ObjectID.BLACK_CHEST, "Black key red").
+ put(ObjectID.BLACK_CHEST_4122, "Black key brown").
+ put(ObjectID.BLACK_CHEST_4123, "Black key crimson").
+ put(ObjectID.BLACK_CHEST_4124, "Black key black").
+ put(ObjectID.BLACK_CHEST_4125, "Black key purple").
+ put(ObjectID.SILVER_CHEST, "Silver key red").
+ put(ObjectID.SILVER_CHEST_4127, "Silver key brown").
+ put(ObjectID.SILVER_CHEST_4128, "Silver key crimson").
+ put(ObjectID.SILVER_CHEST_4129, "Silver key black").
+ put(ObjectID.SILVER_CHEST_4130, "Silver key purple").
+ put(ObjectID.GOLD_CHEST, "Gold key red").
+ put(ObjectID.GOLD_CHEST_41213, "Gold key brown").
+ put(ObjectID.GOLD_CHEST_41214, "Gold key crimson").
+ put(ObjectID.GOLD_CHEST_41215, "Gold key black").
+ put(ObjectID.GOLD_CHEST_41216, "Gold key purple").
+ build();
- // Aggregate of all kills
- private final List aggregateRecords = new ArrayList<>();
- // Individual records for the individual kills this session
- private final List sessionRecords = new ArrayList<>();
- private final List boxes = new ArrayList<>();
+ // Hallow Sepulchre Coffin handling
+ private static final String COFFIN_LOOTED_MESSAGE = "You push the coffin lid aside.";
+ private static final String HALLOWED_SEPULCHRE_COFFIN_EVENT = "Coffin (Hallowed Sepulchre)";
+ private static final Set HALLOWED_SEPULCHRE_MAP_REGIONS = ImmutableSet.of(8797, 10077, 9308, 10074, 9050); // one map region per floor
- private final ItemManager itemManager;
- private final LootTrackerPlugin plugin;
- private final LootTrackerConfig config;
+ private static final String HALLOWED_SACK_EVENT = "Hallowed Sack";
- private boolean groupLoot;
- private boolean hideIgnoredItems;
- private String currentView;
- private LootRecordType currentType;
+ // Last man standing map regions
+ private static final Set LAST_MAN_STANDING_REGIONS = ImmutableSet.of(13658, 13659, 13660, 13914, 13915, 13916, 13918, 13919, 13920, 14174, 14175, 14176, 14430, 14431, 14432);
- static
- {
- final BufferedImage singleLootImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "single_loot_icon.png");
- final BufferedImage groupedLootImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "grouped_loot_icon.png");
- final BufferedImage backArrowImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "back_icon.png");
- final BufferedImage visibleImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "visible_icon.png");
- final BufferedImage invisibleImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "invisible_icon.png");
- final BufferedImage collapseImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "collapsed.png");
- final BufferedImage expandedImg = ImageUtil.loadImageResource(LootTrackerPlugin.class, "expanded.png");
+ private static final Pattern PICKPOCKET_REGEX = Pattern.compile("You pick (the )?(?.+)'s? pocket.*");
- SINGLE_LOOT_VIEW = new ImageIcon(singleLootImg);
- SINGLE_LOOT_VIEW_FADED = new ImageIcon(ImageUtil.alphaOffset(singleLootImg, -180));
- SINGLE_LOOT_VIEW_HOVER = new ImageIcon(ImageUtil.alphaOffset(singleLootImg, -220));
+ private static final String BIRDNEST_EVENT = "Bird nest";
+ private static final Set BIRDNEST_IDS = ImmutableSet.of(ItemID.BIRD_NEST, ItemID.BIRD_NEST_5071, ItemID.BIRD_NEST_5072, ItemID.BIRD_NEST_5073, ItemID.BIRD_NEST_5074, ItemID.BIRD_NEST_7413, ItemID.BIRD_NEST_13653, ItemID.BIRD_NEST_22798, ItemID.BIRD_NEST_22800);
- GROUPED_LOOT_VIEW = new ImageIcon(groupedLootImg);
- GROUPED_LOOT_VIEW_FADED = new ImageIcon(ImageUtil.alphaOffset(groupedLootImg, -180));
- GROUPED_LOOT_VIEW_HOVER = new ImageIcon(ImageUtil.alphaOffset(groupedLootImg, -220));
+ // Birdhouses
+ private static final Pattern BIRDHOUSE_PATTERN = Pattern.compile("You dismantle and discard the trap, retrieving (?:(?:a|\\d{1,2}) nests?, )?10 dead birds, \\d{1,3} feathers and (\\d,?\\d{1,3}) Hunter XP\\.");
+ private static final Map BIRDHOUSE_XP_TO_TYPE = new ImmutableMap.Builder().
+ put(280, "Regular Bird House").
+ put(420, "Oak Bird House").
+ put(560, "Willow Bird House").
+ put(700, "Teak Bird House").
+ put(820, "Maple Bird House").
+ put(960, "Mahogany Bird House").
+ put(1020, "Yew Bird House").
+ put(1140, "Magic Bird House").
+ put(1200, "Redwood Bird House").
+ build();
- BACK_ARROW_ICON = new ImageIcon(backArrowImg);
- BACK_ARROW_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(backArrowImg, -180));
-
- VISIBLE_ICON = new ImageIcon(visibleImg);
- VISIBLE_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(visibleImg, -220));
-
- INVISIBLE_ICON = new ImageIcon(invisibleImg);
- INVISIBLE_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(invisibleImg, -220));
-
- COLLAPSE_ICON = new ImageIcon(collapseImg);
- EXPAND_ICON = new ImageIcon(expandedImg);
- }
-
- LootTrackerPanel(final LootTrackerPlugin plugin, final ItemManager itemManager, final LootTrackerConfig config)
- {
- this.itemManager = itemManager;
- this.plugin = plugin;
- this.config = config;
- this.hideIgnoredItems = true;
-
- setBorder(new EmptyBorder(6, 6, 6, 6));
- setBackground(ColorScheme.DARK_GRAY_COLOR);
- setLayout(new BorderLayout());
-
- // Create layout panel for wrapping
- final JPanel layoutPanel = new JPanel();
- layoutPanel.setLayout(new BoxLayout(layoutPanel, BoxLayout.Y_AXIS));
- add(layoutPanel, BorderLayout.NORTH);
-
- actionsPanel = buildActionsPanel();
- overallPanel = buildOverallPanel();
-
- // Create loot boxes wrapper
- logsContainer.setLayout(new BoxLayout(logsContainer, BoxLayout.Y_AXIS));
- layoutPanel.add(actionsPanel);
- layoutPanel.add(overallPanel);
- layoutPanel.add(logsContainer);
-
- // Add error pane
- errorPanel.setContent("Loot tracker", "You have not received any loot yet.");
- add(errorPanel);
- }
-
- /**
- * The actions panel includes the back/title label for the current view,
- * as well as the view controls panel which includes hidden, single/grouped, and
- * collapse buttons.
+ /*
+ * This map is used when a pickpocket target has a different name in the chat message than their in-game name.
+ * Note that if the two NPCs can be found in the same place, there is a chance of race conditions
+ * occurring when changing targets mid-pickpocket, in which case a different solution may need to be considered.
*/
- private JPanel buildActionsPanel()
+ private static final Multimap PICKPOCKET_DISAMBIGUATION_MAP = ImmutableMultimap.of(
+ "H.A.M. Member", "Man",
+ "H.A.M. Member", "Woman"
+ );
+
+ private static final String CASKET_EVENT = "Casket";
+
+ private static final String WINTERTODT_SUPPLY_CRATE_EVENT = "Supply crate (Wintertodt)";
+
+ // Soul Wars
+ private static final String SPOILS_OF_WAR_EVENT = "Spoils of war";
+ private static final Set 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;
+
+ // Mahogany Homes
+ private static final String MAHOGANY_CRATE_EVENT = "Supply crate (Mahogany Homes)";
+
+ // Implings
+ private static final Set IMPLING_JARS = ImmutableSet.of(
+ ItemID.BABY_IMPLING_JAR,
+ ItemID.YOUNG_IMPLING_JAR,
+ ItemID.GOURMET_IMPLING_JAR,
+ ItemID.EARTH_IMPLING_JAR,
+ ItemID.ESSENCE_IMPLING_JAR,
+ ItemID.ECLECTIC_IMPLING_JAR,
+ ItemID.NATURE_IMPLING_JAR,
+ ItemID.MAGPIE_IMPLING_JAR,
+ ItemID.NINJA_IMPLING_JAR,
+ ItemID.CRYSTAL_IMPLING_JAR,
+ ItemID.DRAGON_IMPLING_JAR,
+ ItemID.LUCKY_IMPLING_JAR
+ );
+ private static final String IMPLING_CATCH_MESSAGE = "You manage to catch the impling and acquire some loot.";
+
+ private static final Set VOWELS = ImmutableSet.of('a', 'e', 'i', 'o', 'u');
+
+ @Inject
+ private ClientToolbar clientToolbar;
+
+ @Inject
+ private ItemManager itemManager;
+
+ @Inject
+ private SpriteManager spriteManager;
+
+ @Inject
+ private LootTrackerConfig config;
+
+ @Inject
+ private Client client;
+
+ @Inject
+ private ClientThread clientThread;
+
+ @Inject
+ private SessionManager sessionManager;
+
+ @Inject
+ private ScheduledExecutorService executor;
+
+ @Inject
+ private EventBus eventBus;
+
+ @Inject
+ private ChatMessageManager chatMessageManager;
+
+ @Inject
+ private LootManager lootManager;
+
+ @Inject
+ private ConfigManager configManager;
+
+ @Inject
+ private Gson gson;
+
+ @Getter(AccessLevel.PACKAGE)
+ @Inject
+ private LootTrackerClient lootTrackerClient;
+
+ private LootTrackerPanel panel;
+ private NavigationButton navButton;
+
+ private boolean chestLooted;
+ private String lastPickpocketTarget;
+
+ private List ignoredItems = new ArrayList<>();
+ private List ignoredEvents = new ArrayList<>();
+
+ private InventoryID inventoryId;
+ private Multiset inventorySnapshot;
+ private InvChangeCallback inventorySnapshotCb;
+
+ private final List queuedLoots = new ArrayList<>();
+ private String profileKey;
+ private Instant lastLootImport = Instant.now().minus(1, ChronoUnit.MINUTES);
+
+ private static Collection stack(Collection items)
{
- final JPanel actionsContainer = new JPanel();
- actionsContainer.setLayout(new BorderLayout());
- actionsContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
- actionsContainer.setPreferredSize(new Dimension(0, 30));
- actionsContainer.setBorder(new EmptyBorder(5, 5, 5, 10));
- actionsContainer.setVisible(false);
+ final List list = new ArrayList<>();
- final JPanel viewControls = new JPanel(new GridLayout(1, 3, 10, 0));
- viewControls.setBackground(ColorScheme.DARKER_GRAY_COLOR);
-
- SwingUtil.removeButtonDecorations(collapseBtn);
- collapseBtn.setIcon(EXPAND_ICON);
- collapseBtn.setSelectedIcon(COLLAPSE_ICON);
- SwingUtil.addModalTooltip(collapseBtn, "Collapse All", "Un-Collapse All");
- collapseBtn.setBackground(ColorScheme.DARKER_GRAY_COLOR);
- collapseBtn.setUI(new BasicButtonUI()); // substance breaks the layout
- collapseBtn.addActionListener(ev -> changeCollapse());
- viewControls.add(collapseBtn);
-
- SwingUtil.removeButtonDecorations(singleLootBtn);
- singleLootBtn.setIcon(SINGLE_LOOT_VIEW_FADED);
- singleLootBtn.setRolloverIcon(SINGLE_LOOT_VIEW_HOVER);
- singleLootBtn.setSelectedIcon(SINGLE_LOOT_VIEW);
- singleLootBtn.setToolTipText("Show each kill separately");
- singleLootBtn.addActionListener(e -> changeGrouping(false));
-
- SwingUtil.removeButtonDecorations(groupedLootBtn);
- groupedLootBtn.setIcon(GROUPED_LOOT_VIEW_FADED);
- groupedLootBtn.setRolloverIcon(GROUPED_LOOT_VIEW_HOVER);
- groupedLootBtn.setSelectedIcon(GROUPED_LOOT_VIEW);
- groupedLootBtn.setToolTipText("Group loot by source");
- groupedLootBtn.addActionListener(e -> changeGrouping(true));
-
- ButtonGroup groupSingleGroup = new ButtonGroup();
- groupSingleGroup.add(singleLootBtn);
- groupSingleGroup.add(groupedLootBtn);
-
- viewControls.add(groupedLootBtn);
- viewControls.add(singleLootBtn);
- changeGrouping(true);
-
- SwingUtil.removeButtonDecorations(viewHiddenBtn);
- viewHiddenBtn.setIconTextGap(0);
- viewHiddenBtn.setIcon(VISIBLE_ICON);
- viewHiddenBtn.setRolloverIcon(INVISIBLE_ICON_HOVER);
- viewHiddenBtn.setSelectedIcon(INVISIBLE_ICON);
- viewHiddenBtn.setRolloverSelectedIcon(VISIBLE_ICON_HOVER);
- viewHiddenBtn.setBackground(ColorScheme.DARKER_GRAY_COLOR);
- viewHiddenBtn.setUI(new BasicToggleButtonUI()); // substance breaks the layout and the pressed icon
- viewHiddenBtn.addActionListener(e -> changeItemHiding(viewHiddenBtn.isSelected()));
- SwingUtil.addModalTooltip(viewHiddenBtn, "Show ignored items", "Hide ignored items");
- changeItemHiding(true);
- viewControls.add(viewHiddenBtn);
-
- final JPanel leftTitleContainer = new JPanel(new BorderLayout(5, 0));
- leftTitleContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
-
- detailsTitle.setForeground(Color.WHITE);
-
- SwingUtil.removeButtonDecorations(backBtn);
- backBtn.setIcon(BACK_ARROW_ICON);
- backBtn.setRolloverIcon(BACK_ARROW_ICON_HOVER);
- backBtn.setVisible(false);
- backBtn.addActionListener(ev ->
+ for (final ItemStack item : items)
{
- currentView = null;
- currentType = null;
- backBtn.setVisible(false);
- detailsTitle.setText("");
- rebuild();
- });
-
- leftTitleContainer.add(backBtn, BorderLayout.WEST);
- leftTitleContainer.add(detailsTitle, BorderLayout.CENTER);
-
- actionsContainer.add(viewControls, BorderLayout.EAST);
- actionsContainer.add(leftTitleContainer, BorderLayout.WEST);
-
- return actionsContainer;
- }
-
- private JPanel buildOverallPanel()
- {
- // Create panel that will contain overall data
- final JPanel overallPanel = new JPanel();
- overallPanel.setBorder(BorderFactory.createCompoundBorder(
- BorderFactory.createMatteBorder(5, 0, 0, 0, ColorScheme.DARK_GRAY_COLOR),
- BorderFactory.createEmptyBorder(8, 10, 8, 10)
- ));
- overallPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
- overallPanel.setLayout(new BorderLayout());
- overallPanel.setVisible(false);
-
- // Add icon and contents
- final JPanel overallInfo = new JPanel();
- overallInfo.setBackground(ColorScheme.DARKER_GRAY_COLOR);
- overallInfo.setLayout(new GridLayout(2, 1));
- overallInfo.setBorder(new EmptyBorder(2, 10, 2, 0));
- overallKillsLabel.setFont(FontManager.getRunescapeSmallFont());
- overallGpLabel.setFont(FontManager.getRunescapeSmallFont());
- overallInfo.add(overallKillsLabel);
- overallInfo.add(overallGpLabel);
- overallPanel.add(overallIcon, BorderLayout.WEST);
- overallPanel.add(overallInfo, BorderLayout.CENTER);
-
- // Create reset all menu
- final JMenuItem reset = new JMenuItem("Reset All");
- reset.addActionListener(e ->
- {
- final int result = JOptionPane.showOptionDialog(overallPanel,
- currentView == null ? RESET_ALL_WARNING_TEXT : String.format(RESET_CURRENT_WARNING_TEXT, currentView),
- "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
- null, new String[]{"Yes", "No"}, "No");
-
- if (result != JOptionPane.YES_OPTION)
+ int quantity = 0;
+ for (final ItemStack i : list)
{
- return;
+ if (i.getId() == item.getId())
+ {
+ quantity = i.getQuantity();
+ list.remove(i);
+ break;
+ }
}
-
- // If not in detailed view, remove all, otherwise only remove for the currently detailed title
- sessionRecords.removeIf(r -> r.matches(currentView, currentType));
- aggregateRecords.removeIf(r -> r.matches(currentView, currentType));
- boxes.removeIf(b -> b.matches(currentView, currentType));
- updateOverall();
- logsContainer.removeAll();
- logsContainer.revalidate();
-
- // Delete all loot, or loot matching the current view
- if (currentView != null)
+ if (quantity > 0)
{
- assert currentType != null;
- plugin.removeLootConfig(currentType, currentView);
+ list.add(new ItemStack(item.getId(), item.getQuantity() + quantity, item.getLocation()));
}
else
{
- plugin.removeAllLoot();
+ list.add(item);
}
- });
+ }
- // Create popup menu
- final JPopupMenu popupMenu = new JPopupMenu();
- popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
- popupMenu.add(reset);
- overallPanel.setComponentPopupMenu(popupMenu);
-
- return overallPanel;
+ return list;
}
- void updateCollapseText()
+ @Provides
+ LootTrackerConfig provideConfig(ConfigManager configManager)
{
- collapseBtn.setSelected(isAllCollapsed());
+ return configManager.getConfig(LootTrackerConfig.class);
}
- private boolean isAllCollapsed()
+ @Subscribe
+ public void onSessionOpen(SessionOpen sessionOpen)
{
- return boxes.stream()
- .filter(LootTrackerBox::isCollapsed)
- .count() == boxes.size();
- }
-
- void loadHeaderIcon(BufferedImage img)
- {
- overallIcon.setIcon(new ImageIcon(img));
- }
-
- /**
- * Adds a new entry to the plugin.
- * Creates a subtitle, adds a new entry and then passes off to the render methods, that will decide
- * how to display this new data.
- */
- void add(final String eventName, final LootRecordType type, final int actorLevel, LootTrackerItem[] items, int kills)
- {
- final String subTitle;
- if (type == LootRecordType.PICKPOCKET)
+ AccountSession accountSession = sessionManager.getAccountSession();
+ if (accountSession.getUuid() != null)
{
- subTitle = "(pickpocket)";
+ lootTrackerClient.setUuid(accountSession.getUuid());
}
else
{
- subTitle = actorLevel > -1 ? "(lvl-" + actorLevel + ")" : "";
+ lootTrackerClient.setUuid(null);
}
- final LootTrackerRecord record = new LootTrackerRecord(eventName, subTitle, type, items, kills);
- sessionRecords.add(record);
+ }
- if (hideIgnoredItems && plugin.isEventIgnored(eventName))
+ @Subscribe
+ public void onSessionClose(SessionClose sessionClose)
+ {
+ submitLoot();
+ lootTrackerClient.setUuid(null);
+ }
+
+ @Subscribe
+ public void onRuneScapeProfileChanged(RuneScapeProfileChanged e)
+ {
+ final String profileKey = configManager.getRSProfileKey();
+ if (profileKey == null)
{
return;
}
- LootTrackerBox box = buildBox(record);
- if (box != null)
+ if (profileKey.equals(this.profileKey))
{
- box.rebuild();
- updateOverall();
+ return;
}
+
+ switchProfile(profileKey);
}
- /**
- * Clear all records in the panel
- */
- void clearRecords()
+ private void switchProfile(String profileKey)
{
- aggregateRecords.clear();
- }
-
- /**
- * Adds a Collection of records to the panel
- */
- void addRecords(Collection recs)
- {
- aggregateRecords.addAll(recs);
- rebuild();
- }
-
- /**
- * Changes grouping mode of panel
- *
- * @param group if loot should be grouped or not
- */
- private void changeGrouping(boolean group)
- {
- groupLoot = group;
- (group ? groupedLootBtn : singleLootBtn).setSelected(true);
- rebuild();
- }
-
- /**
- * Changes item hiding mode of panel
- *
- * @param hide if ignored items should be hidden or not
- */
- private void changeItemHiding(boolean hide)
- {
- hideIgnoredItems = hide;
- viewHiddenBtn.setSelected(hide);
- rebuild();
- }
-
- /**
- * Changes the collapse status of loot entries
- */
- private void changeCollapse()
- {
- boolean isAllCollapsed = isAllCollapsed();
-
- for (LootTrackerBox box : boxes)
+ executor.execute(() ->
{
- if (isAllCollapsed)
- {
- box.expand();
- }
- else if (!box.isCollapsed())
- {
- box.collapse();
- }
- }
+ // Current queued loot is for the previous profile, so save it first with the current profile key
+ submitLoot();
- updateCollapseText();
- }
+ this.profileKey = profileKey;
- /**
- * After an item changed it's ignored state, iterate all the records and make
- * sure all items of the same name also get updated
- */
- void updateIgnoredRecords()
- {
- for (LootTrackerRecord record : concat(aggregateRecords, sessionRecords))
- {
- for (LootTrackerItem item : record.getItems())
- {
- item.setIgnored(plugin.isIgnored(item.getName()));
- }
- }
+ log.debug("Switched to profile {}", profileKey);
- rebuild();
- }
-
- /**
- * Rebuilds all the boxes from scratch using existing listed records, depending on the grouping mode.
- */
- private void rebuild()
- {
- SwingUtil.fastRemoveAll(logsContainer);
- boxes.clear();
-
- if (groupLoot)
- {
- aggregateRecords.forEach(this::buildBox);
- sessionRecords.forEach(this::buildBox);
- }
- else
- {
- // Loop in reverse insertion order so limiting includes most recent data
- Lists.reverse(sessionRecords).stream()
- // filter records prior to limiting so that it is limited to the correct amount
- .filter(r -> !hideIgnoredItems || !plugin.isEventIgnored(r.getTitle()))
- .limit(MAX_LOOT_BOXES)
- // The box that is built last is first inside the UI.
- // since we are looping in reverse order we need to use a data type that support reverse iterating
- .collect(Collectors.toCollection(ArrayDeque::new))
- .descendingIterator()
- .forEachRemaining(this::buildBox);
- }
-
- boxes.forEach(LootTrackerBox::rebuild);
- updateOverall();
- logsContainer.revalidate();
- }
-
- /**
- * This method decides what to do with a new record, if a similar log exists, it will
- * add its items to it, updating the log's overall price and kills. If not, a new log will be created
- * to hold this entry's information.
- */
- private LootTrackerBox buildBox(LootTrackerRecord record)
- {
- // If this record is not part of current view, return
- if (!record.matches(currentView, currentType))
- {
- return null;
- }
-
- final boolean isIgnored = plugin.isEventIgnored(record.getTitle());
- if (hideIgnoredItems && isIgnored)
- {
- return null;
- }
-
- // Group all similar loot together
- if (groupLoot)
- {
- for (LootTrackerBox box : boxes)
- {
- if (box.matches(record))
- {
- // float the matched box to the top of the UI list if it's not already first
- logsContainer.setComponentZOrder(box, 0);
- box.addKill(record);
- return box;
- }
- }
- }
-
- // Show main view
- remove(errorPanel);
- actionsPanel.setVisible(true);
- overallPanel.setVisible(true);
-
- // Create box
- final LootTrackerBox box = new LootTrackerBox(itemManager, record.getTitle(), record.getType(), record.getSubTitle(),
- hideIgnoredItems, config.priceType(), config.showPriceType(), plugin::toggleItem, plugin::toggleEvent, isIgnored);
- box.addKill(record);
-
- // Use the existing popup menu or create a new one
- JPopupMenu popupMenu = box.getComponentPopupMenu();
- if (popupMenu == null)
- {
- popupMenu = new JPopupMenu();
- popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
- box.setComponentPopupMenu(popupMenu);
- }
-
- // Create collapse event
- box.addMouseListener(new MouseAdapter()
- {
- @Override
- public void mouseClicked(MouseEvent e)
- {
- if (e.getButton() == MouseEvent.BUTTON1)
- {
- if (box.isCollapsed())
- {
- box.expand();
- }
- else
- {
- box.collapse();
- }
- updateCollapseText();
- }
- }
- });
-
- // Create reset menu
- final JMenuItem reset = new JMenuItem("Reset");
- reset.addActionListener(e ->
- {
- final int result = JOptionPane.showOptionDialog(box,
- groupLoot ? String.format(RESET_CURRENT_WARNING_TEXT, box.getId()) : RESET_ONE_WARNING_TEXT,
- "Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
- null, new String[]{"Yes", "No"}, "No");
-
- if (result != JOptionPane.YES_OPTION)
+ if (!config.syncPanel())
{
return;
}
- Predicate match = groupLoot
- // With grouped loot, remove any record with this title
- ? r -> r.matches(record.getTitle(), record.getType())
- // Otherwise remove specifically this entry
- : r -> r.equals(record);
- sessionRecords.removeIf(match);
- aggregateRecords.removeIf(match);
- boxes.remove(box);
- updateOverall();
- logsContainer.remove(box);
- logsContainer.revalidate();
-
- // Without loot being grouped we have no way to identify single kills to be deleted
- if (groupLoot)
+ int drops = 0;
+ List loots = new ArrayList<>();
+ Instant old = Instant.now().minus(MAX_AGE);
+ for (String key : configManager.getRSProfileConfigurationKeys(LootTrackerConfig.GROUP, profileKey, "drops_"))
{
- plugin.removeLootConfig(box.getLootRecordType(), box.getId());
- }
- });
+ String json = configManager.getConfiguration(LootTrackerConfig.GROUP, profileKey, key);
+ ConfigLoot configLoot;
- popupMenu.add(reset);
-
- // Create details menu
- final JMenuItem details = new JMenuItem("View details");
- details.addActionListener(e ->
- {
- currentView = record.getTitle();
- currentType = record.getType();
- detailsTitle.setText(currentView);
- backBtn.setVisible(true);
- rebuild();
- });
-
- popupMenu.add(details);
-
- // Add box to panel
- boxes.add(box);
- logsContainer.add(box, 0);
-
- if (!groupLoot && boxes.size() > MAX_LOOT_BOXES)
- {
- logsContainer.remove(boxes.remove(0));
- }
-
- return box;
- }
-
- private void updateOverall()
- {
- long overallKills = 0;
- long overallGe = 0;
- long overallHa = 0;
-
- Iterable records = sessionRecords;
- if (groupLoot)
- {
- records = concat(aggregateRecords, sessionRecords);
- }
-
- for (LootTrackerRecord record : records)
- {
- if (!record.matches(currentView, currentType))
- {
- continue;
- }
-
- if (hideIgnoredItems && plugin.isEventIgnored(record.getTitle()))
- {
- continue;
- }
-
- int present = record.getItems().length;
-
- for (LootTrackerItem item : record.getItems())
- {
- if (hideIgnoredItems && item.isIgnored())
+ try
{
- present--;
+ configLoot = gson.fromJson(json, ConfigLoot.class);
+ }
+ catch (JsonSyntaxException ex)
+ {
+ log.warn("Removing loot with malformed json: {}", json, ex);
+ configManager.unsetConfiguration(LootTrackerConfig.GROUP, profileKey, key);
continue;
}
- overallGe += item.getTotalGePrice();
- overallHa += item.getTotalHaPrice();
+ if (configLoot.last.isBefore(old))
+ {
+ log.debug("Removing old loot for {} {}", configLoot.type, configLoot.name);
+ configManager.unsetConfiguration(LootTrackerConfig.GROUP, profileKey, key);
+ continue;
+ }
+
+ if (drops >= MAX_DROPS && !loots.isEmpty() && loots.get(0).last.isAfter(configLoot.last))
+ {
+ // fast drop
+ continue;
+ }
+
+ sortedInsert(loots, configLoot, Comparator.comparing(ConfigLoot::getLast));
+ drops += configLoot.numDrops();
+
+ if (drops >= MAX_DROPS)
+ {
+ ConfigLoot top = loots.remove(0);
+ drops -= top.numDrops();
+ }
}
- if (present > 0)
+ log.debug("Loaded {} records", loots.size());
+
+ clientThread.invokeLater(() ->
{
- overallKills += record.getKills();
+ // convertToLootTrackerRecord must be called on client thread
+ List records = loots.stream()
+ .map(this::convertToLootTrackerRecord)
+ .collect(Collectors.toList());
+ SwingUtilities.invokeLater(() ->
+ {
+ panel.clearRecords();
+ panel.addRecords(records);
+ });
+ });
+ });
+ }
+
+ private static void sortedInsert(List list, T value, Comparator super T> c)
+ {
+ int idx = Collections.binarySearch(list, value, c);
+ list.add(idx < 0 ? -idx - 1 : idx, value);
+ }
+
+ @Subscribe
+ public void onConfigChanged(ConfigChanged event)
+ {
+ if (event.getGroup().equals(LootTrackerConfig.GROUP))
+ {
+ if ("ignoredItems".equals(event.getKey()) || "ignoredEvents".equals(event.getKey()))
+ {
+ ignoredItems = Text.fromCSV(config.getIgnoredItems());
+ ignoredEvents = Text.fromCSV(config.getIgnoredEvents());
+ SwingUtilities.invokeLater(panel::updateIgnoredRecords);
+ }
+ }
+ }
+
+ @Override
+ protected void startUp() throws Exception
+ {
+ profileKey = null;
+ ignoredItems = Text.fromCSV(config.getIgnoredItems());
+ ignoredEvents = Text.fromCSV(config.getIgnoredEvents());
+ panel = new LootTrackerPanel(this, itemManager, config);
+ spriteManager.getSpriteAsync(SpriteID.TAB_INVENTORY, 0, panel::loadHeaderIcon);
+
+ final BufferedImage icon = ImageUtil.loadImageResource(getClass(), "panel_icon.png");
+
+ navButton = NavigationButton.builder()
+ .tooltip("Loot Tracker")
+ .icon(icon)
+ .priority(5)
+ .panel(panel)
+ .build();
+
+ clientToolbar.addNavigation(navButton);
+
+ AccountSession accountSession = sessionManager.getAccountSession();
+ if (accountSession != null)
+ {
+ lootTrackerClient.setUuid(accountSession.getUuid());
+ }
+
+ String profileKey = configManager.getRSProfileKey();
+ if (profileKey != null)
+ {
+ switchProfile(profileKey);
+ }
+ }
+
+ @Override
+ protected void shutDown()
+ {
+ submitLoot();
+ clientToolbar.removeNavigation(navButton);
+ lootTrackerClient.setUuid(null);
+ chestLooted = false;
+ }
+
+ @Subscribe
+ public void onClientShutdown(ClientShutdown event)
+ {
+ Future future = submitLoot();
+ if (future != null)
+ {
+ event.waitFor(future);
+ }
+ }
+
+ @Subscribe
+ public void onGameStateChanged(final GameStateChanged event)
+ {
+ if (event.getGameState() == GameState.LOADING && !client.isInInstancedRegion())
+ {
+ chestLooted = false;
+ }
+ }
+
+ void addLoot(@NonNull String name, int combatLevel, LootRecordType type, Object metadata, Collection items)
+ {
+ addLoot(name, combatLevel, type, metadata, items, 1);
+ }
+
+ void addLoot(@NonNull String name, int combatLevel, LootRecordType type, Object metadata, Collection items, int amount)
+ {
+ final LootTrackerItem[] entries = buildEntries(stack(items));
+ SwingUtilities.invokeLater(() -> panel.add(name, type, combatLevel, entries, amount));
+
+ LootRecord lootRecord = new LootRecord(name, type, metadata, toGameItems(items), Instant.now(), getLootWorldId());
+ synchronized (queuedLoots)
+ {
+ queuedLoots.add(lootRecord);
+ }
+
+ eventBus.post(new LootReceived(name, combatLevel, type, items, amount));
+ }
+
+ private Integer getLootWorldId()
+ {
+ // For the wiki to determine drop rates based on dmm brackets / identify leagues drops
+ return client.getWorldType().contains(WorldType.SEASONAL) ? client.getWorld() : null;
+ }
+
+ @Subscribe
+ public void onNpcLootReceived(final NpcLootReceived npcLootReceived)
+ {
+ final NPC npc = npcLootReceived.getNpc();
+ final Collection items = npcLootReceived.getItems();
+ final String name = npc.getName();
+ final int combat = npc.getCombatLevel();
+
+ addLoot(name, combat, LootRecordType.NPC, npc.getId(), items);
+
+ if (config.npcKillChatMessage())
+ {
+ final String prefix = VOWELS.contains(Character.toLowerCase(name.charAt(0)))
+ ? "an"
+ : "a";
+
+ lootReceivedChatMessage(items, prefix + ' ' + name);
+ }
+ }
+
+ @Subscribe
+ public void onPlayerLootReceived(final PlayerLootReceived playerLootReceived)
+ {
+ // Ignore Last Man Standing and Soul Wars player loots
+ if (isPlayerWithinMapRegion(LAST_MAN_STANDING_REGIONS) || isPlayerWithinMapRegion(SOUL_WARS_REGIONS))
+ {
+ return;
+ }
+
+ final Player player = playerLootReceived.getPlayer();
+ final Collection items = playerLootReceived.getItems();
+ final String name = player.getName();
+ final int combat = player.getCombatLevel();
+
+ addLoot(name, combat, LootRecordType.PLAYER, null, items);
+
+ if (config.pvpKillChatMessage())
+ {
+ lootReceivedChatMessage(items, name);
+ }
+ }
+
+ @Subscribe
+ public void onWidgetLoaded(WidgetLoaded widgetLoaded)
+ {
+ String event;
+ Object metadata = null;
+ final ItemContainer container;
+
+ switch (widgetLoaded.getGroupId())
+ {
+ case (WidgetID.BARROWS_REWARD_GROUP_ID):
+ event = "Barrows";
+ container = client.getItemContainer(InventoryID.BARROWS_REWARD);
+ break;
+ case (WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID):
+ if (chestLooted)
+ {
+ return;
+ }
+ event = "Chambers of Xeric";
+ container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST);
+ chestLooted = true;
+ break;
+ case (WidgetID.THEATRE_OF_BLOOD_GROUP_ID):
+ if (chestLooted)
+ {
+ return;
+ }
+ int region = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID();
+ if (region != THEATRE_OF_BLOOD_REGION && region != THEATRE_OF_BLOOD_LOBBY)
+ {
+ return;
+ }
+ event = "Theatre of Blood";
+ container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST);
+ chestLooted = true;
+ break;
+ case (WidgetID.KINGDOM_GROUP_ID):
+ event = "Kingdom of Miscellania";
+ container = client.getItemContainer(InventoryID.KINGDOM_OF_MISCELLANIA);
+ break;
+ case (WidgetID.FISHING_TRAWLER_REWARD_GROUP_ID):
+ event = "Fishing Trawler";
+ metadata = client.getBoostedSkillLevel(Skill.FISHING);
+ container = client.getItemContainer(InventoryID.FISHING_TRAWLER_REWARD);
+ break;
+ case (WidgetID.DRIFT_NET_FISHING_REWARD_GROUP_ID):
+ event = "Drift Net";
+ metadata = client.getBoostedSkillLevel(Skill.FISHING);
+ container = client.getItemContainer(InventoryID.DRIFT_NET_FISHING_REWARD);
+ break;
+ case WidgetID.WILDERNESS_LOOT_CHEST:
+ if (chestLooted)
+ {
+ return;
+ }
+ event = "Loot Chest";
+ container = client.getItemContainer(InventoryID.WILDERNESS_LOOT_CHEST);
+ chestLooted = true;
+ break;
+ default:
+ return;
+ }
+
+ if (container == null)
+ {
+ return;
+ }
+
+ // Convert container items to array of ItemStack
+ final Collection items = Arrays.stream(container.getItems())
+ .filter(item -> item.getId() > 0)
+ .map(item -> new ItemStack(item.getId(), item.getQuantity(), client.getLocalPlayer().getLocalLocation()))
+ .collect(Collectors.toList());
+
+ if (config.showRaidsLootValue() && (event.equals("Theatre of Blood") || event.equals("Chambers of Xeric")))
+ {
+ long totalValue = items.stream()
+ .filter(item -> item.getId() > -1)
+ .mapToLong(item -> config.priceType() == LootTrackerPriceType.GRAND_EXCHANGE ?
+ (long) itemManager.getItemPrice(item.getId()) * item.getQuantity() :
+ (long) itemManager.getItemComposition(item.getId()).getHaPrice() * item.getQuantity())
+ .sum();
+
+ String chatMessage = new ChatMessageBuilder()
+ .append(ChatColorType.NORMAL)
+ .append("Your loot is worth around ")
+ .append(ChatColorType.HIGHLIGHT)
+ .append(QuantityFormatter.formatNumber(totalValue))
+ .append(ChatColorType.NORMAL)
+ .append(" coins.")
+ .build();
+
+ chatMessageManager.queue(QueuedMessage.builder()
+ .type(ChatMessageType.FRIENDSCHATNOTIFICATION)
+ .runeLiteFormattedMessage(chatMessage)
+ .build());
+ }
+
+ if (items.isEmpty())
+ {
+ log.debug("No items to find for Event: {} | Container: {}", event, container);
+ return;
+ }
+
+ addLoot(event, -1, LootRecordType.EVENT, metadata, items);
+ }
+
+ @Subscribe
+ public void onChatMessage(ChatMessage event)
+ {
+ if (event.getType() != ChatMessageType.GAMEMESSAGE && event.getType() != ChatMessageType.SPAM)
+ {
+ return;
+ }
+
+ final String message = event.getMessage();
+
+ if (message.equals(CHEST_LOOTED_MESSAGE) || message.equals(OTHER_CHEST_LOOTED_MESSAGE)
+ || message.equals(DORGESH_KAAN_CHEST_LOOTED_MESSAGE) || message.startsWith(GRUBBY_CHEST_LOOTED_MESSAGE)
+ || LARRAN_LOOTED_PATTERN.matcher(message).matches() || ROGUES_CHEST_PATTERN.matcher(message).matches())
+ {
+ final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
+ if (!CHEST_EVENT_TYPES.containsKey(regionID))
+ {
+ return;
+ }
+
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, CHEST_EVENT_TYPES.get(regionID)));
+ return;
+ }
+
+ if (message.equals(COFFIN_LOOTED_MESSAGE) &&
+ isPlayerWithinMapRegion(HALLOWED_SEPULCHRE_MAP_REGIONS))
+ {
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HALLOWED_SEPULCHRE_COFFIN_EVENT));
+ return;
+ }
+
+ if (message.equals(HERBIBOAR_LOOTED_MESSAGE))
+ {
+ if (processHerbiboarHerbSackLoot(event.getTimestamp()))
+ {
+ return;
+ }
+
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HERBIBOAR_EVENT, client.getBoostedSkillLevel(Skill.HERBLORE)));
+ return;
+ }
+
+ final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
+ if (HESPORI_REGION == regionID && message.equals(HESPORI_LOOTED_MESSAGE))
+ {
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HESPORI_EVENT));
+ return;
+ }
+
+ final Matcher hamStoreroomMatcher = HAM_CHEST_LOOTED_PATTERN.matcher(message);
+ if (hamStoreroomMatcher.matches() && regionID == HAM_STOREROOM_REGION)
+ {
+ String keyType = hamStoreroomMatcher.group("key");
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, String.format("H.A.M. chest (%s)", keyType)));
+ return;
+ }
+
+ final Matcher pickpocketMatcher = PICKPOCKET_REGEX.matcher(message);
+ if (pickpocketMatcher.matches())
+ {
+ // Get the target's name as listed in the chat box
+ String pickpocketTarget = WordUtils.capitalize(pickpocketMatcher.group("target"));
+
+ // Occasional edge case where the pickpocket message doesn't list the correct name of the NPC (e.g. H.A.M. Members)
+ if (PICKPOCKET_DISAMBIGUATION_MAP.get(lastPickpocketTarget).contains(pickpocketTarget))
+ {
+ pickpocketTarget = lastPickpocketTarget;
+ }
+
+ onInvChange(collectInvAndGroundItems(LootRecordType.PICKPOCKET, pickpocketTarget));
+ return;
+ }
+
+ // Check if message is for a clue scroll reward
+ final Matcher m = CLUE_SCROLL_PATTERN.matcher(Text.removeTags(message));
+ if (m.find())
+ {
+ final String type = m.group(1).toLowerCase();
+ String eventType;
+ switch (type)
+ {
+ case "beginner":
+ eventType = "Clue Scroll (Beginner)";
+ break;
+ case "easy":
+ eventType = "Clue Scroll (Easy)";
+ break;
+ case "medium":
+ eventType = "Clue Scroll (Medium)";
+ break;
+ case "hard":
+ eventType = "Clue Scroll (Hard)";
+ break;
+ case "elite":
+ eventType = "Clue Scroll (Elite)";
+ break;
+ case "master":
+ eventType = "Clue Scroll (Master)";
+ break;
+ default:
+ log.debug("Unrecognized clue type: {}", type);
+ return;
+ }
+
+ // Clue Scrolls use same InventoryID as Barrows
+ onInvChange(InventoryID.BARROWS_REWARD, collectInvItems(LootRecordType.EVENT, eventType));
+
+ return;
+ }
+
+ if (SHADE_CHEST_NO_KEY_PATTERN.matcher(message).matches())
+ {
+ // Player didn't have the key they needed.
+ resetEvent();
+ return;
+ }
+
+ // Check if message is a birdhouse type
+ final Matcher matcher = BIRDHOUSE_PATTERN.matcher(message);
+ if (matcher.matches())
+ {
+ final int xp = Integer.parseInt(matcher.group(1));
+ final String type = BIRDHOUSE_XP_TO_TYPE.get(xp);
+ if (type == null)
+ {
+ log.debug("Unknown bird house type {}", xp);
+ return;
+ }
+
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, type, client.getBoostedSkillLevel(Skill.HUNTER)));
+ return;
+ }
+
+ if (regionID == TEMPOROSS_REGION && message.startsWith(TEMPOROSS_LOOT_STRING))
+ {
+ onInvChange(collectInvItems(LootRecordType.EVENT, TEMPOROSS_EVENT, client.getBoostedSkillLevel(Skill.FISHING)));
+ return;
+ }
+
+ if (message.equals(IMPLING_CATCH_MESSAGE))
+ {
+ onInvChange(collectInvItems(LootRecordType.EVENT, client.getLocalPlayer().getInteracting().getName()));
+ return;
+ }
+ }
+
+ @Subscribe
+ public void onItemContainerChanged(ItemContainerChanged event)
+ {
+ // when the wilderness chest empties, clear chest loot flag for the next key
+ if (event.getContainerId() == InventoryID.WILDERNESS_LOOT_CHEST.getId()
+ && Arrays.stream(event.getItemContainer().getItems()).noneMatch(i -> i.getId() > -1))
+ {
+ log.debug("Resetting chest loot flag");
+ chestLooted = false;
+ }
+
+ if (inventoryId == null || event.getContainerId() != inventoryId.getId())
+ {
+ return;
+ }
+
+ final ItemContainer inventoryContainer = event.getItemContainer();
+ Multiset currentInventory = HashMultiset.create();
+ Arrays.stream(inventoryContainer.getItems())
+ .forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
+
+ WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
+ final Collection groundItems = lootManager.getItemSpawns(playerLocation);
+
+ final Multiset diff = Multisets.difference(currentInventory, inventorySnapshot);
+ final Multiset diffr = Multisets.difference(inventorySnapshot, currentInventory);
+
+ final List items = diff.entrySet().stream()
+ .map(e -> new ItemStack(e.getElement(), e.getCount(), client.getLocalPlayer().getLocalLocation()))
+ .collect(Collectors.toList());
+
+ log.debug("Inv change: {} Ground items: {}", items, groundItems);
+
+ if (inventorySnapshotCb != null)
+ {
+ inventorySnapshotCb.accept(items, groundItems, diffr);
+ }
+
+ inventoryId = null;
+ inventorySnapshot = null;
+ inventorySnapshotCb = null;
+ }
+
+ @Subscribe
+ public void onMenuOptionClicked(MenuOptionClicked event)
+ {
+ // There are some pickpocket targets who show up in the chat box with a different name (e.g. H.A.M. members -> man/woman)
+ // We use the value selected from the right-click menu as a fallback for the event lookup in those cases.
+ if (isNPCOp(event.getMenuAction()) && event.getMenuOption().equals("Pickpocket"))
+ {
+ lastPickpocketTarget = Text.removeTags(event.getMenuTarget());
+ }
+ else if (isObjectOp(event.getMenuAction()) && event.getMenuOption().equals("Open") && SHADE_CHEST_OBJECTS.containsKey(event.getId()))
+ {
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, SHADE_CHEST_OBJECTS.get(event.getId())));
+ }
+ else if (isItemOp(event.getMenuAction()))
+ {
+ if (event.getMenuOption().equals("Take") && event.getId() == ItemID.SEED_PACK)
+ {
+ onInvChange(collectInvItems(LootRecordType.EVENT, SEEDPACK_EVENT));
+ }
+ else if (event.getMenuOption().equals("Search") && BIRDNEST_IDS.contains(event.getId()))
+ {
+ onInvChange(collectInvItems(LootRecordType.EVENT, BIRDNEST_EVENT));
+ }
+ else if (event.getMenuOption().equals("Open"))
+ {
+ switch (event.getId())
+ {
+ case ItemID.CASKET:
+ onInvChange(collectInvItems(LootRecordType.EVENT, CASKET_EVENT));
+ break;
+ case ItemID.SUPPLY_CRATE:
+ case ItemID.EXTRA_SUPPLY_CRATE:
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, WINTERTODT_SUPPLY_CRATE_EVENT));
+ break;
+ case ItemID.SPOILS_OF_WAR:
+ onInvChange(collectInvItems(LootRecordType.EVENT, SPOILS_OF_WAR_EVENT));
+ break;
+ case ItemID.CASKET_25590:
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, TEMPOROSS_CASKET_EVENT));
+ break;
+ case ItemID.SIMPLE_LOCKBOX_25647:
+ case ItemID.ELABORATE_LOCKBOX_25649:
+ case ItemID.ORNATE_LOCKBOX_25651:
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, itemManager.getItemComposition(event.getId()).getName()));
+ break;
+ case ItemID.SUPPLY_CRATE_24884:
+ onInvChange(collectInvItems(LootRecordType.EVENT, MAHOGANY_CRATE_EVENT, client.getBoostedSkillLevel(Skill.CONSTRUCTION)));
+ break;
+ case ItemID.HALLOWED_SACK:
+ onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, HALLOWED_SACK_EVENT));
+ break;
+ }
+ }
+ else if (event.getMenuOption().equals("Loot") && IMPLING_JARS.contains(event.getId()))
+ {
+ onInvChange(((invItems, groundItems, removedItems) ->
+ {
+ int cnt = removedItems.count(event.getId());
+ if (cnt > 0)
+ {
+ String name = itemManager.getItemComposition(event.getId()).getName();
+ addLoot(name, -1, LootRecordType.EVENT, null, invItems, cnt);
+ }
+ }));
+ }
+ }
+ }
+
+ @Subscribe
+ public void onCommandExecuted(CommandExecuted commandExecuted)
+ {
+ if (commandExecuted.getCommand().equals("importloot"))
+ {
+ SwingUtilities.invokeLater(this::importLoot);
+ }
+ }
+
+ private static boolean isItemOp(MenuAction menuAction)
+ {
+ final int id = menuAction.getId();
+ return id >= MenuAction.ITEM_FIRST_OPTION.getId() && id <= MenuAction.ITEM_FIFTH_OPTION.getId();
+ }
+
+ private static boolean isNPCOp(MenuAction menuAction)
+ {
+ final int id = menuAction.getId();
+ return id >= MenuAction.NPC_FIRST_OPTION.getId() && id <= MenuAction.NPC_FIFTH_OPTION.getId();
+ }
+
+ private static boolean isObjectOp(MenuAction menuAction)
+ {
+ final int id = menuAction.getId();
+ return (id >= MenuAction.GAME_OBJECT_FIRST_OPTION.getId() && id <= MenuAction.GAME_OBJECT_FOURTH_OPTION.getId())
+ || id == MenuAction.GAME_OBJECT_FIFTH_OPTION.getId();
+ }
+
+ @Schedule(
+ period = 5,
+ unit = ChronoUnit.MINUTES,
+ asynchronous = true
+ )
+ public void submitLootTask()
+ {
+ submitLoot();
+ }
+
+ @Nullable
+ private CompletableFuture submitLoot()
+ {
+ List copy;
+ synchronized (queuedLoots)
+ {
+ if (queuedLoots.isEmpty())
+ {
+ return null;
+ }
+
+ copy = new ArrayList<>(queuedLoots);
+ queuedLoots.clear();
+ }
+
+ saveLoot(copy);
+
+ log.debug("Submitting {} loot records", copy.size());
+
+ return lootTrackerClient.submit(copy);
+ }
+
+ private Collection combine(List records)
+ {
+ Map map = new HashMap<>();
+ for (LootRecord record : records)
+ {
+ ConfigLoot key = new ConfigLoot(record.getType(), record.getEventId());
+ ConfigLoot loot = map.computeIfAbsent(key, k -> key);
+ loot.kills++;
+ for (GameItem item : record.getDrops())
+ {
+ loot.add(item.getId(), item.getQty());
+ }
+ }
+ return map.values();
+ }
+
+ private void saveLoot(List records)
+ {
+ Instant now = Instant.now();
+ Collection combinedRecords = combine(records);
+ for (ConfigLoot record : combinedRecords)
+ {
+ ConfigLoot lootConfig = getLootConfig(record.type, record.name);
+ if (lootConfig == null)
+ {
+ lootConfig = record;
+ }
+ else
+ {
+ lootConfig.kills += record.kills;
+ for (int i = 0; i < record.drops.length; i += 2)
+ {
+ lootConfig.add(record.drops[i], record.drops[i + 1]);
+ }
+ }
+ lootConfig.last = now;
+ setLootConfig(lootConfig.type, lootConfig.name, lootConfig);
+ }
+ }
+
+ private void resetEvent()
+ {
+ inventoryId = null;
+ inventorySnapshot = null;
+ inventorySnapshotCb = null;
+ }
+
+ @FunctionalInterface
+ interface InvChangeCallback
+ {
+ void accept(Collection invItems, Collection groundItems, Multiset removedItems);
+ }
+
+ private InvChangeCallback collectInvItems(LootRecordType type, String event)
+ {
+ return collectInvItems(type, event, null);
+ }
+
+ private InvChangeCallback collectInvItems(LootRecordType type, String event, Object metadata)
+ {
+ return (invItems, groundItems, removedItems) ->
+ addLoot(event, -1, type, metadata, invItems);
+ }
+
+ private InvChangeCallback collectInvAndGroundItems(LootRecordType type, String event)
+ {
+ return collectInvAndGroundItems(type, event, null);
+ }
+
+ private InvChangeCallback collectInvAndGroundItems(LootRecordType type, String event, Object metadata)
+ {
+ return (invItems, groundItems, removedItems) ->
+ {
+ List combined = new ArrayList<>();
+ combined.addAll(invItems);
+ combined.addAll(groundItems);
+ addLoot(event, -1, type, metadata, combined);
+ };
+ }
+
+ private void onInvChange(InvChangeCallback cb)
+ {
+ onInvChange(InventoryID.INVENTORY, cb);
+ }
+
+ private void onInvChange(InventoryID inv, InvChangeCallback cb)
+ {
+ inventoryId = inv;
+ inventorySnapshot = HashMultiset.create();
+ inventorySnapshotCb = cb;
+
+ final ItemContainer itemContainer = client.getItemContainer(inv);
+ if (itemContainer != null)
+ {
+ Arrays.stream(itemContainer.getItems())
+ .forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
+ }
+ }
+
+ private boolean processHerbiboarHerbSackLoot(int timestamp)
+ {
+ List herbs = new ArrayList<>();
+
+ for (MessageNode messageNode : client.getMessages())
+ {
+ if (messageNode.getTimestamp() != timestamp
+ || messageNode.getType() != ChatMessageType.SPAM)
+ {
+ continue;
+ }
+
+ Matcher matcher = HERBIBOAR_HERB_SACK_PATTERN.matcher(messageNode.getValue());
+ if (matcher.matches())
+ {
+ herbs.add(new ItemStack(itemManager.search(matcher.group(1)).get(0).getId(), 1, client.getLocalPlayer().getLocalLocation()));
}
}
- String priceType = "";
- if (config.showPriceType())
+ if (herbs.isEmpty())
{
- priceType = config.priceType() == LootTrackerPriceType.HIGH_ALCHEMY ? "HA " : "GE ";
+ return false;
}
- overallKillsLabel.setText(htmlLabel("Total count: ", overallKills));
- overallGpLabel.setText(htmlLabel("Total " + priceType + "value: ", config.priceType() == LootTrackerPriceType.HIGH_ALCHEMY ? overallHa : overallGe));
- overallGpLabel.setToolTipText("Total GE price: " + QuantityFormatter.formatNumber(overallGe)
- + "
Total HA price: " + QuantityFormatter.formatNumber(overallHa) + "");
- updateCollapseText();
+ int herbloreLevel = client.getBoostedSkillLevel(Skill.HERBLORE);
+ addLoot(HERBIBOAR_EVENT, -1, LootRecordType.EVENT, herbloreLevel, herbs);
+ return true;
}
- private static String htmlLabel(String key, long value)
+ void toggleItem(String name, boolean ignore)
{
- final String valueStr = QuantityFormatter.quantityToStackSize(value);
- return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr);
+ final Set ignoredItemSet = new LinkedHashSet<>(ignoredItems);
+
+ if (ignore)
+ {
+ ignoredItemSet.add(name);
+ }
+ else
+ {
+ ignoredItemSet.remove(name);
+ }
+
+ config.setIgnoredItems(Text.toCSV(ignoredItemSet));
+ // the config changed will update the panel
}
-}
\ No newline at end of file
+
+ boolean isIgnored(String name)
+ {
+ return ignoredItems.contains(name);
+ }
+
+ void toggleEvent(String name, boolean ignore)
+ {
+ final Set ignoredSet = new LinkedHashSet<>(ignoredEvents);
+
+ if (ignore)
+ {
+ ignoredSet.add(name);
+ }
+ else
+ {
+ ignoredSet.remove(name);
+ }
+
+ config.setIgnoredEvents(Text.toCSV(ignoredSet));
+ // the config changed will update the panel
+ }
+
+ boolean isEventIgnored(String name)
+ {
+ return ignoredEvents.contains(name);
+ }
+
+ private LootTrackerItem buildLootTrackerItem(int itemId, int quantity)
+ {
+ final ItemComposition itemComposition = itemManager.getItemComposition(itemId);
+ final int gePrice = itemManager.getItemPrice(itemId);
+ final int haPrice = itemComposition.getHaPrice();
+ final boolean ignored = ignoredItems.contains(itemComposition.getName());
+
+ return new LootTrackerItem(
+ itemId,
+ itemComposition.getName(),
+ quantity,
+ gePrice,
+ haPrice,
+ ignored);
+ }
+
+ private LootTrackerItem[] buildEntries(final Collection itemStacks)
+ {
+ return itemStacks.stream()
+ .map(itemStack -> buildLootTrackerItem(itemStack.getId(), itemStack.getQuantity()))
+ .toArray(LootTrackerItem[]::new);
+ }
+
+ private static Collection toGameItems(Collection items)
+ {
+ return items.stream()
+ .map(item -> new GameItem(item.getId(), item.getQuantity()))
+ .collect(Collectors.toList());
+ }
+
+ private Collection convertToLootTrackerRecord(final Collection records)
+ {
+ return records.stream()
+ .sorted(Comparator.comparing(LootAggregate::getLast_time))
+ .map(record ->
+ {
+ LootTrackerItem[] drops = record.getDrops().stream().map(itemStack ->
+ buildLootTrackerItem(itemStack.getId(), itemStack.getQty())
+ ).toArray(LootTrackerItem[]::new);
+
+ return new LootTrackerRecord(record.getEventId(), "", record.getType(), drops, record.getAmount());
+ })
+ .collect(Collectors.toCollection(ArrayList::new));
+ }
+
+ private LootTrackerRecord convertToLootTrackerRecord(final ConfigLoot configLoot)
+ {
+ LootTrackerItem[] items = new LootTrackerItem[configLoot.drops.length / 2];
+ for (int i = 0; i < configLoot.drops.length; i += 2)
+ {
+ int id = configLoot.drops[i];
+ int qty = configLoot.drops[i + 1];
+ items[i >> 1] = buildLootTrackerItem(id, qty);
+ }
+ return new LootTrackerRecord(configLoot.name, "", configLoot.type, items, configLoot.kills);
+ }
+
+ /**
+ * Is player currently within the provided map regions
+ */
+ private boolean isPlayerWithinMapRegion(Set definedMapRegions)
+ {
+ final int[] mapRegions = client.getMapRegions();
+
+ for (int region : mapRegions)
+ {
+ if (definedMapRegions.contains(region))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void lootReceivedChatMessage(final Collection items, final String name)
+ {
+ long totalPrice = items.stream()
+ .mapToLong(is -> (long) itemManager.getItemPrice(is.getId()) * is.getQuantity())
+ .sum();
+
+ final String message = new ChatMessageBuilder()
+ .append(ChatColorType.HIGHLIGHT)
+ .append("You've killed ")
+ .append(name)
+ .append(" for ")
+ .append(QuantityFormatter.quantityToStackSize(totalPrice))
+ .append(" loot.")
+ .build();
+
+ chatMessageManager.queue(
+ QueuedMessage.builder()
+ .type(ChatMessageType.CONSOLE)
+ .runeLiteFormattedMessage(message)
+ .build());
+ }
+
+ ConfigLoot getLootConfig(LootRecordType type, String name)
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ log.debug("Trying to get loot with no profile!");
+ return null;
+ }
+
+ String json = configManager.getConfiguration(LootTrackerConfig.GROUP, profile, "drops_" + type + "_" + name);
+ if (json == null)
+ {
+ return null;
+ }
+
+ return gson.fromJson(json, ConfigLoot.class);
+ }
+
+ void setLootConfig(LootRecordType type, String name, ConfigLoot loot)
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ log.debug("Trying to set loot with no profile!");
+ return;
+ }
+
+ String json = gson.toJson(loot);
+ configManager.setConfiguration(LootTrackerConfig.GROUP, profile, "drops_" + type + "_" + name, json);
+ }
+
+ void removeLootConfig(LootRecordType type, String name)
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ log.debug("Trying to remove loot with no profile!");
+ return;
+ }
+
+ configManager.unsetConfiguration(LootTrackerConfig.GROUP, profile, "drops_" + type + "_" + name);
+ }
+
+ void removeAllLoot()
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ log.debug("Trying to clear loot with no profile!");
+ return;
+ }
+
+ for (String key : configManager.getRSProfileConfigurationKeys(LootTrackerConfig.GROUP, profile, "drops_"))
+ {
+ configManager.unsetConfiguration(LootTrackerConfig.GROUP, profile, key);
+ }
+
+ clearImported();
+ }
+
+ void importLoot()
+ {
+ if (configManager.getRSProfileKey() == null)
+ {
+ JOptionPane.showMessageDialog(panel, "You do not have an active profile to import loot into; log in to the game first.");
+ return;
+ }
+
+ if (lootTrackerClient.getUuid() == null)
+ {
+ JOptionPane.showMessageDialog(panel, "You are not logged into RuneLite, so loot can not be imported from your account. Log in first.");
+ return;
+ }
+
+ if (lastLootImport.isAfter(Instant.now().minus(1, ChronoUnit.MINUTES)))
+ {
+ JOptionPane.showMessageDialog(panel, "You imported too recently. Wait a minute and try again.");
+ return;
+ }
+
+ lastLootImport = Instant.now();
+
+ executor.execute(() ->
+ {
+ if (hasImported())
+ {
+ SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(panel, "You already have imported loot."));
+ return;
+ }
+
+ Collection lootRecords;
+ try
+ {
+ lootRecords = lootTrackerClient.get();
+ }
+ catch (IOException e)
+ {
+ log.debug("Unable to look up loot", e);
+ return;
+ }
+
+ log.debug("Loaded {} data entries", lootRecords.size());
+
+ for (LootAggregate record : lootRecords)
+ {
+ ConfigLoot lootConfig = getLootConfig(record.getType(), record.getEventId());
+ if (lootConfig == null)
+ {
+ lootConfig = new ConfigLoot(record.getType(), record.getEventId());
+ }
+ lootConfig.first = record.getFirst_time();
+ lootConfig.last = record.getLast_time();
+ lootConfig.kills += record.getAmount();
+ for (GameItem gameItem : record.getDrops())
+ {
+ lootConfig.add(gameItem.getId(), gameItem.getQty());
+ }
+ setLootConfig(record.getType(), record.getEventId(), lootConfig);
+ }
+
+ clientThread.invokeLater(() ->
+ {
+ Collection records = convertToLootTrackerRecord(lootRecords);
+ SwingUtilities.invokeLater(() -> panel.addRecords(records));
+ });
+
+ SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(panel, "Imported " + lootRecords.size() + " loot entries."));
+
+ setHasImported();
+ });
+ }
+
+ void setHasImported()
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ return;
+ }
+
+ configManager.setConfiguration(LootTrackerConfig.GROUP, profile, "imported", 1);
+ }
+
+ boolean hasImported()
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ return false;
+ }
+
+ Integer i = configManager.getConfiguration(LootTrackerConfig.GROUP, profile, "imported", Integer.class);
+ return i != null && i == 1;
+ }
+
+ void clearImported()
+ {
+ String profile = profileKey;
+ if (Strings.isNullOrEmpty(profile))
+ {
+ return;
+ }
+
+ configManager.unsetConfiguration(LootTrackerConfig.GROUP, profile, "imported");
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java
deleted file mode 100644
index 6bf52d1a36..0000000000
--- a/runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2019 Spudjb
- * 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.questlist;
-
-import com.google.common.collect.ImmutableList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.inject.Inject;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.Getter;
-import net.runelite.api.Client;
-import net.runelite.api.GameState;
-import net.runelite.api.ScriptID;
-import net.runelite.api.SoundEffectID;
-import net.runelite.api.SpriteID;
-import net.runelite.api.VarClientInt;
-import net.runelite.api.Varbits;
-import net.runelite.api.events.GameStateChanged;
-import net.runelite.api.events.ScriptPostFired;
-import net.runelite.api.events.VarClientIntChanged;
-import net.runelite.api.events.VarbitChanged;
-import net.runelite.api.widgets.JavaScriptCallback;
-import net.runelite.api.widgets.Widget;
-import net.runelite.api.widgets.WidgetInfo;
-import net.runelite.api.widgets.WidgetPositionMode;
-import net.runelite.api.widgets.WidgetType;
-import net.runelite.client.callback.ClientThread;
-import net.runelite.client.eventbus.Subscribe;
-import net.runelite.client.game.chatbox.ChatboxPanelManager;
-import net.runelite.client.game.chatbox.ChatboxTextInput;
-import net.runelite.client.plugins.Plugin;
-import net.runelite.client.plugins.PluginDescriptor;
-import net.runelite.client.util.Text;
-
-@PluginDescriptor(
- name = "Quest List",
- description = "Adds searching and filtering to the quest list"
-)
-public class QuestListPlugin extends Plugin
-{
- private static final int ENTRY_PADDING = 8;
- private static final List QUEST_HEADERS = ImmutableList.of("Free Quests", "Members' Quests", "Miniquests");
-
- private static final String MENU_OPEN = "Open";
- private static final String MENU_CLOSE = "Close";
-
- private static final String MENU_TOGGLE = "Toggle";
-
- private static final String MENU_SEARCH = "Search";
- private static final String MENU_SHOW = "Show";
-
- @Inject
- private Client client;
-
- @Inject
- private ChatboxPanelManager chatboxPanelManager;
-
- @Inject
- private ClientThread clientThread;
-
- private ChatboxTextInput searchInput;
- private Widget questSearchButton;
- private Widget questHideButton;
-
- private EnumMap> questSet;
-
- private QuestState currentFilterState;
-
- @Override
- protected void startUp()
- {
- currentFilterState = QuestState.ALL;
- clientThread.invoke(this::addQuestButtons);
- }
-
- @Override
- protected void shutDown()
- {
- currentFilterState = null;
- Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
- if (header != null)
- {
- header.deleteAllChildren();
- }
- }
-
- @Subscribe
- public void onGameStateChanged(GameStateChanged e)
- {
- if (e.getGameState() == GameState.LOGGING_IN)
- {
- currentFilterState = QuestState.ALL;
- }
- }
-
- @Subscribe
- public void onScriptPostFired(ScriptPostFired event)
- {
- if (event.getScriptId() != ScriptID.QUESTLIST_PROGRESS_LIST_SHOW)
- {
- return;
- }
- addQuestButtons();
- }
-
- private void addQuestButtons()
- {
- Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
- if (header != null)
- {
- header.deleteAllChildren();
-
- questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
- questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
- questSearchButton.setOriginalWidth(18);
- questSearchButton.setOriginalHeight(17);
- questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
- questSearchButton.setOriginalX(5);
- questSearchButton.setOriginalY(0);
- questSearchButton.setHasListener(true);
- questSearchButton.setAction(1, MENU_OPEN);
- questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
- questSearchButton.setName(MENU_SEARCH);
- questSearchButton.revalidate();
-
- questHideButton = header.createChild(-1, WidgetType.GRAPHIC);
- redrawHideButton();
-
- questHideButton.setOriginalWidth(13);
- questHideButton.setOriginalHeight(13);
- questHideButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
- questHideButton.setOriginalX(24);
- questHideButton.setOriginalY(2);
- questHideButton.setHasListener(true);
- questHideButton.setOnOpListener((JavaScriptCallback) e -> toggleHidden());
- questHideButton.setAction(1, MENU_TOGGLE);
- questHideButton.revalidate();
-
- questSet = new EnumMap<>(QuestContainer.class);
-
- updateFilter();
- }
- }
-
- @Subscribe
- public void onVarbitChanged(VarbitChanged varbitChanged)
- {
- if (isChatboxOpen() && !isOnQuestTab())
- {
- chatboxPanelManager.close();
- }
- }
-
- @Subscribe
- public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
- {
- if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
- {
- if (isChatboxOpen() && !isOnQuestTab())
- {
- chatboxPanelManager.close();
- }
- }
- }
-
- private void toggleHidden()
- {
- QuestState[] questStates = QuestState.values();
- int nextState = (currentFilterState.ordinal() + 1) % questStates.length;
- currentFilterState = questStates[nextState];
-
- redrawHideButton();
-
- updateFilter();
- client.playSoundEffect(SoundEffectID.UI_BOOP);
- }
-
- private void redrawHideButton()
- {
- questHideButton.setSpriteId(currentFilterState.getSpriteId());
- questHideButton.setName(MENU_SHOW + " " + currentFilterState.getName());
- }
-
- private boolean isOnQuestTab()
- {
- return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
- }
-
- private boolean isChatboxOpen()
- {
- return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
- }
-
- private void closeSearch()
- {
- updateFilter("");
- chatboxPanelManager.close();
- client.playSoundEffect(SoundEffectID.UI_BOOP);
- }
-
- private void openSearch()
- {
- updateFilter("");
- client.playSoundEffect(SoundEffectID.UI_BOOP);
- questSearchButton.setAction(1, MENU_CLOSE);
- questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
- searchInput = chatboxPanelManager.openTextInput("Search quest list")
- .onChanged(s -> clientThread.invokeLater(() -> updateFilter(s)))
- .onDone(s -> false)
- .onClose(() ->
- {
- clientThread.invokeLater(() -> updateFilter(""));
- questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
- questSearchButton.setAction(1, MENU_OPEN);
- })
- .build();
- }
-
- private void updateFilter()
- {
- String filter = "";
- if (isChatboxOpen())
- {
- filter = searchInput.getValue();
- }
-
- updateFilter(filter);
- }
-
- private void updateFilter(String filter)
- {
- filter = filter.toLowerCase();
- final Widget container = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
-
- final Widget freeList = client.getWidget(QuestContainer.FREE_QUESTS.widgetInfo);
- final Widget memberList = client.getWidget(QuestContainer.MEMBER_QUESTS.widgetInfo);
- final Widget miniList = client.getWidget(QuestContainer.MINI_QUESTS.widgetInfo);
-
- if (container == null || freeList == null || memberList == null || miniList == null)
- {
- return;
- }
-
- updateList(QuestContainer.FREE_QUESTS, filter);
- updateList(QuestContainer.MEMBER_QUESTS, filter);
- updateList(QuestContainer.MINI_QUESTS, filter);
-
- memberList.setOriginalY(freeList.getOriginalY() + freeList.getOriginalHeight() + ENTRY_PADDING);
- miniList.setOriginalY(memberList.getOriginalY() + memberList.getOriginalHeight() + ENTRY_PADDING);
-
- // originalHeight is changed within updateList so revalidate all lists
- freeList.revalidate();
- memberList.revalidate();
- miniList.revalidate();
-
- int y = miniList.getRelativeY() + miniList.getHeight() + 10;
-
- int newHeight;
- if (container.getScrollHeight() > 0)
- {
- newHeight = (container.getScrollY() * y) / container.getScrollHeight();
- }
- else
- {
- newHeight = 0;
- }
-
- container.setScrollHeight(y);
- container.revalidateScroll();
-
- clientThread.invokeLater(() ->
- client.runScript(
- ScriptID.UPDATE_SCROLLBAR,
- WidgetInfo.QUESTLIST_SCROLLBAR.getId(),
- WidgetInfo.QUESTLIST_CONTAINER.getId(),
- newHeight
- ));
- }
-
- private void updateList(QuestContainer questContainer, String filter)
- {
- Widget list = client.getWidget(questContainer.widgetInfo);
- if (list == null)
- {
- return;
- }
-
- Collection quests = questSet.get(questContainer);
-
- if (quests != null)
- {
- // Check to make sure the list hasn't been rebuild since we were last her
- // Do this by making sure the list's dynamic children are the same as when we last saw them
- if (quests.stream().noneMatch(w ->
- {
- Widget codeWidget = w.getQuest();
- if (codeWidget == null)
- {
- return false;
- }
- return list.getChild(codeWidget.getIndex()) == codeWidget;
- }))
- {
- quests = null;
- }
- }
-
- if (quests == null)
- {
- // Find all of the widgets that we care about, sorting by their Y value
- quests = Arrays.stream(list.getDynamicChildren())
- .sorted(Comparator.comparingInt(Widget::getRelativeY))
- .filter(w -> !QUEST_HEADERS.contains(w.getText()))
- .map(w -> new QuestWidget(w, Text.removeTags(w.getText()).toLowerCase()))
- .collect(Collectors.toList());
- questSet.put(questContainer, quests);
- }
-
- // offset because of header
- int y = 20;
- for (QuestWidget questInfo : quests)
- {
- Widget quest = questInfo.getQuest();
- QuestState questState = QuestState.getByColor(quest.getTextColor());
-
- boolean hidden;
- if (!filter.isEmpty())
- {
- // If searching, show result regardless of filtered state
- hidden = !questInfo.getTitle().contains(filter);
- }
- else
- {
- // Otherwise hide if it doesn't match the filter state
- if (currentFilterState == QuestState.NOT_COMPLETED)
- {
- hidden = questState == QuestState.COMPLETE;
- }
- else
- {
- hidden = currentFilterState != QuestState.ALL && questState != currentFilterState;
- }
- }
-
- quest.setHidden(hidden);
- quest.setOriginalY(y);
- quest.revalidate();
-
- if (!hidden)
- {
- y += quest.getHeight();
- }
- }
-
- list.setOriginalHeight(y);
- }
-
- @AllArgsConstructor
- @Getter
- private enum QuestContainer
- {
- FREE_QUESTS(WidgetInfo.QUESTLIST_FREE_CONTAINER),
- MEMBER_QUESTS(WidgetInfo.QUESTLIST_MEMBERS_CONTAINER),
- MINI_QUESTS(WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER);
-
- private final WidgetInfo widgetInfo;
- }
-
- @AllArgsConstructor
- @Getter
- private enum QuestState
- {
- NOT_STARTED(0xff0000, "Not started", SpriteID.MINIMAP_ORB_HITPOINTS),
- IN_PROGRESS(0xffff00, "In progress", SpriteID.MINIMAP_ORB_HITPOINTS_DISEASE),
- COMPLETE(0xdc10d, "Completed", SpriteID.MINIMAP_ORB_HITPOINTS_POISON),
- ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER),
- NOT_COMPLETED(0, "Not Completed", SpriteID.MINIMAP_ORB_RUN);
-
- private final int color;
- private final String name;
- private final int spriteId;
-
- static QuestState getByColor(int color)
- {
- for (QuestState value : values())
- {
- if (value.getColor() == color)
- {
- return value;
- }
- }
-
- return null;
- }
- }
-
- @Data
- @AllArgsConstructor
- private static class QuestWidget
- {
- private Widget quest;
- private String title;
- }
-}
diff --git a/runelite-client/src/main/resources/item_variations.json b/runelite-client/src/main/resources/item_variations.json
index 4d99b9390d..1f5c3764d3 100644
--- a/runelite-client/src/main/resources/item_variations.json
+++ b/runelite-client/src/main/resources/item_variations.json
@@ -253,16 +253,10 @@
282,
283
],
- "notes": [
+ "research notes": [
291,
- 20770,
- 20771,
- 20772,
- 21056,
- 21057,
- 21058,
- 26276,
- 26596
+ 10492,
+ 25824
],
"glarials urn": [
296,
@@ -3282,7 +3276,25 @@
3682,
3683,
3684,
- 3685
+ 3685,
+ 26656,
+ 26657,
+ 26658,
+ 26659,
+ 26660,
+ 26661,
+ 26662,
+ 26663,
+ 26664,
+ 26665,
+ 26666,
+ 26667,
+ 26668,
+ 26669,
+ 26670,
+ 26671,
+ 26672,
+ 26673
],
"enchanted lyre": [
3690,
@@ -3561,7 +3573,9 @@
12017,
12018,
25250,
- 25278
+ 25278,
+ 26763,
+ 26782
],
"sled": [
4083,
@@ -4959,23 +4973,27 @@
6731,
11770,
23624,
- 25258
+ 25258,
+ 26767
],
"archers ring": [
6733,
11771,
- 25260
+ 25260,
+ 26768
],
"warrior ring": [
6735,
11772,
- 25262
+ 25262,
+ 26769
],
"berserker ring": [
6737,
11773,
23595,
- 25264
+ 25264,
+ 26770
],
"dragon axe": [
6739,
@@ -6313,7 +6331,18 @@
25273,
25274,
25275,
- 25276
+ 25276,
+ 26771,
+ 26772,
+ 26773,
+ 26774,
+ 26775,
+ 26776,
+ 26777,
+ 26778,
+ 26779,
+ 26780,
+ 26781
],
"bandana eyepatch": [
8924,
@@ -6791,10 +6820,6 @@
10340,
20577
],
- "research notes": [
- 10492,
- 25824
- ],
"avas accumulator": [
10499,
23609
@@ -7466,9 +7491,30 @@
11820,
11822
],
+ "armadyl helmet": [
+ 11826,
+ 26714
+ ],
+ "armadyl chestplate": [
+ 11828,
+ 26715
+ ],
+ "armadyl chainskirt": [
+ 11830,
+ 26716
+ ],
+ "bandos chestplate": [
+ 11832,
+ 26718
+ ],
"bandos tassets": [
11834,
- 23646
+ 23646,
+ 26719
+ ],
+ "bandos boots": [
+ 11836,
+ 26720
],
"dragon boots": [
11840,
@@ -7643,7 +7689,18 @@
25908,
25910,
25912,
- 25914
+ 25914,
+ 26674,
+ 26675,
+ 26676,
+ 26677,
+ 26678,
+ 26679,
+ 26680,
+ 26681,
+ 26682,
+ 26683,
+ 26684
],
"slayer ring": [
11866,
@@ -7735,17 +7792,20 @@
"ring of the gods": [
12601,
13202,
- 25252
+ 25252,
+ 26764
],
"tyrannical ring": [
12603,
12691,
- 25254
+ 25254,
+ 26765
],
"treasonous ring": [
12605,
12692,
- 25256
+ 25256,
+ 26766
],
"book of war": [
12608,
@@ -8438,7 +8498,8 @@
],
"dragon warhammer": [
13576,
- 20785
+ 20785,
+ 26710
],
"seed box": [
13639,
@@ -8467,7 +8528,8 @@
],
"dragon claws": [
13652,
- 20784
+ 20784,
+ 26708
],
"bag of gems": [
19473,
@@ -8476,7 +8538,8 @@
],
"heavy ballista": [
19481,
- 23630
+ 23630,
+ 26712
],
"dragon javelin": [
19484,
@@ -8516,7 +8579,9 @@
20655,
20657,
25246,
- 25248
+ 25248,
+ 26761,
+ 26762
],
"amulet of torture": [
19553,
@@ -8655,6 +8720,16 @@
20769,
21055
],
+ "notes": [
+ 20770,
+ 20771,
+ 20772,
+ 21056,
+ 21057,
+ 21058,
+ 26276,
+ 26596
+ ],
"killers knife": [
20781,
21059
@@ -8911,7 +8986,8 @@
"granite ring": [
21739,
21752,
- 25193
+ 25193,
+ 26685
],
"royal accord of twill": [
21758,
@@ -9212,6 +9288,10 @@
22500,
22502
],
+ "escape crystal": [
+ 22517,
+ 25961
+ ],
"coin pouch": [
22521,
22522,
@@ -10397,5 +10477,153 @@
26653,
26654,
26655
+ ],
+ "maomas med helm": [
+ 26686,
+ 26743,
+ 26744
+ ],
+ "maomas helm": [
+ 26687,
+ 26745,
+ 26746
+ ],
+ "maomas great helm": [
+ 26688,
+ 26747,
+ 26748
+ ],
+ "calamity chest": [
+ 26689,
+ 26749,
+ 26750
+ ],
+ "superior calamity chest": [
+ 26690,
+ 26751,
+ 26752
+ ],
+ "elite calamity chest": [
+ 26691,
+ 26753,
+ 26754
+ ],
+ "calamity breeches": [
+ 26692,
+ 26755,
+ 26756
+ ],
+ "superior calamity breeches": [
+ 26693,
+ 26757,
+ 26758
+ ],
+ "elite calamity breeches": [
+ 26694,
+ 26759,
+ 26760
+ ],
+ "centurion cuirass": [
+ 26695,
+ 26721,
+ 26722
+ ],
+ "wristbands of the arena": [
+ 26696,
+ 26723,
+ 26724,
+ 26725,
+ 26726,
+ 26727,
+ 26728,
+ 26729,
+ 26730
+ ],
+ "koriffs headband": [
+ 26698,
+ 26737,
+ 26738
+ ],
+ "koriffs cowl": [
+ 26699,
+ 26739,
+ 26740
+ ],
+ "koriffs coif": [
+ 26700,
+ 26741,
+ 26742
+ ],
+ "saikas hood": [
+ 26701,
+ 26731,
+ 26732
+ ],
+ "saikas veil": [
+ 26702,
+ 26733,
+ 26734
+ ],
+ "saikas shroud": [
+ 26703,
+ 26735,
+ 26736
+ ],
+ "colossal pouch": [
+ 26784,
+ 26786,
+ 26906
+ ],
+ "ring of the elements": [
+ 26815,
+ 26818
+ ],
+ "abyssal lantern": [
+ 26822,
+ 26824,
+ 26826,
+ 26828,
+ 26830,
+ 26832,
+ 26834,
+ 26836,
+ 26838,
+ 26840,
+ 26842,
+ 26844,
+ 26846,
+ 26848
+ ],
+ "hat of the eye": [
+ 26850,
+ 26858,
+ 26864,
+ 26870
+ ],
+ "robe top of the eye": [
+ 26852,
+ 26860,
+ 26866,
+ 26872
+ ],
+ "robe bottoms of the eye": [
+ 26854,
+ 26862,
+ 26868,
+ 26874
+ ],
+ "portal talisman": [
+ 26887,
+ 26888,
+ 26889,
+ 26890,
+ 26891,
+ 26892,
+ 26893,
+ 26894,
+ 26895,
+ 26896,
+ 26897,
+ 26898
]
}
\ No newline at end of file
diff --git a/runelite-client/src/main/scripts/ChatSend.hash b/runelite-client/src/main/scripts/ChatSend.hash
index 1e7ae9ee97..eafdef4142 100644
--- a/runelite-client/src/main/scripts/ChatSend.hash
+++ b/runelite-client/src/main/scripts/ChatSend.hash
@@ -1 +1 @@
-95E7960E289ECA35DEADD35BC5A34AEBAA1C9F367AC42A71A5F3EFCCA0600D10
\ No newline at end of file
+9DD950503D89B0A449488A4642B4810F076835EAEDB21AAB69544B359A35CD8A
\ No newline at end of file
diff --git a/runelite-client/src/main/scripts/ChatSend.rs2asm b/runelite-client/src/main/scripts/ChatSend.rs2asm
index e4e8725cbf..9461bf176b 100644
--- a/runelite-client/src/main/scripts/ChatSend.rs2asm
+++ b/runelite-client/src/main/scripts/ChatSend.rs2asm
@@ -6,7 +6,7 @@
get_varbit 4394
iconst 1
if_icmpeq LABEL4
- jump LABEL23
+ jump LABEL24
LABEL4:
iload 0
iconst 1
@@ -30,41 +30,43 @@ LABEL16:
join_string 5
mes
LABEL23:
+ return
+LABEL24:
invoke 5262
iconst 0
- if_icmpeq LABEL27
- jump LABEL33
-LABEL27:
+ if_icmpeq LABEL28
+ jump LABEL34
+LABEL28:
iload 3
iconst 4
- if_icmpeq LABEL31
- jump LABEL33
-LABEL31:
+ if_icmpeq LABEL32
+ jump LABEL34
+LABEL32:
get_varc_int 945
istore 3
-LABEL33:
+LABEL34:
iload 3
iconst -1
- if_icmpne LABEL37
- jump LABEL70
-LABEL37:
+ if_icmpne LABEL38
+ jump LABEL71
+LABEL38:
iload 3
iconst 4
- if_icmple LABEL41
- jump LABEL70
-LABEL41:
+ if_icmple LABEL42
+ jump LABEL71
+LABEL42:
iload 3
get_varc_int 945
- if_icmpne LABEL45
- jump LABEL70
-LABEL45:
+ if_icmpne LABEL46
+ jump LABEL71
+LABEL46:
iload 3
set_varc_int 945
iload 3
iconst 0
- if_icmpne LABEL51
- jump LABEL61
-LABEL51:
+ if_icmpne LABEL52
+ jump LABEL62
+LABEL52:
sconst "Your chatbox mode is now set to "
iconst 105
iconst 115
@@ -74,8 +76,8 @@ LABEL51:
sconst " chat, to reset your mode type /@p"
join_string 3
mes
- jump LABEL70
-LABEL61:
+ jump LABEL71
+LABEL62:
sconst "Your chatbox mode has been reset to "
iconst 105
iconst 115
@@ -85,28 +87,28 @@ LABEL61:
sconst " chat."
join_string 3
mes
-LABEL70:
+LABEL71:
iload 2
iconst 1
- if_icmpeq LABEL74
- jump LABEL112
-LABEL74:
+ if_icmpeq LABEL75
+ jump LABEL113
+LABEL75:
get_varc_int 945
switch
- 1: LABEL77
- 2: LABEL98
- 3: LABEL103
- 4: LABEL108
- jump LABEL112
-LABEL77:
+ 1: LABEL78
+ 2: LABEL99
+ 3: LABEL104
+ 4: LABEL109
+ jump LABEL113
+LABEL78:
iconst 2
istore 0
sload 0
string_length
iconst 0
- if_icmpgt LABEL84
- jump LABEL97
-LABEL84:
+ if_icmpgt LABEL85
+ jump LABEL98
+LABEL85:
sload 0
iconst 0
iconst 1
@@ -114,33 +116,33 @@ LABEL84:
sconst "/"
compare
iconst 0 ;
- if_icmpne LABEL93
- jump LABEL97
-LABEL93:
+ if_icmpne LABEL94
+ jump LABEL98
+LABEL94:
sconst "/"
sload 0
append
sstore 0
-LABEL97:
- jump LABEL112
LABEL98:
+ jump LABEL113
+LABEL99:
iconst 3
iconst 0
istore 1
istore 0
- jump LABEL112
-LABEL103:
+ jump LABEL113
+LABEL104:
iconst 4
iconst 0
istore 1
istore 0
- jump LABEL112
-LABEL108:
+ jump LABEL113
+LABEL109:
iconst 3
iconst 1
istore 1
istore 0
-LABEL112:
+LABEL113:
sload 0 ; load input
iload 0 ; load chat type
iload 1 ; load clan target
@@ -157,31 +159,31 @@ CONTINUE:
sstore 1
iload 0
iconst 2
- if_icmpeq LABEL124
+ if_icmpeq LABEL125
iload 0
iconst 3
- if_icmpeq LABEL124
+ if_icmpeq LABEL125
iload 0
iconst 4
- if_icmpeq LABEL124
- jump LABEL164
-LABEL124:
+ if_icmpeq LABEL125
+ jump LABEL175
+LABEL125:
sload 0
invoke 5501
iconst 1
- if_icmpeq LABEL129
- jump LABEL133
-LABEL129:
+ if_icmpeq LABEL130
+ jump LABEL134
+LABEL130:
sload 0
invoke 632
sstore 0
sstore 1
-LABEL133:
+LABEL134:
iload 1
iconst 1
- if_icmpeq LABEL137
- jump LABEL153
-LABEL137:
+ if_icmpeq LABEL138
+ jump LABEL164
+LABEL138:
sload 0
iconst 0
iconst 1
@@ -198,20 +200,17 @@ LABEL137:
sload 0
append
sstore 0
-LABEL153:
sload 0
string_length
- iconst 0
- if_icmple LABEL158
- jump LABEL159
-LABEL158:
- return
+ iconst 80
+ if_icmpgt LABEL159
+ jump LABEL164
LABEL159:
sload 0
- iload 0
- iload 1
- chat_sendclan
- jump LABEL173
+ iconst 0
+ iconst 80
+ substring
+ sstore 0
LABEL164:
sload 0
string_length
@@ -221,10 +220,24 @@ LABEL164:
LABEL169:
return
LABEL170:
+ sload 0
+ iload 0
+ iload 1
+ chat_sendclan
+ jump LABEL184
+LABEL175:
+ sload 0
+ string_length
+ iconst 0
+ if_icmple LABEL180
+ jump LABEL181
+LABEL180:
+ return
+LABEL181:
sload 0
iload 0
chat_sendpublic
-LABEL173:
+LABEL184:
clientclock
set_varc_int 61
return
diff --git a/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.hash b/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.hash
index 5bce54b6ad..eb47ec489b 100644
--- a/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.hash
+++ b/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.hash
@@ -1 +1 @@
-E4001956B7EAAB914D97C392358D20A95B1EFD929278D8CBC380C7354418D345
\ No newline at end of file
+7D493EF06AAA3BE49BCCB9E0A5F4EC5A4EDC5280D4965D3C0140CC691F8946F4
\ No newline at end of file
diff --git a/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.rs2asm b/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.rs2asm
index f5174ac072..499f375092 100644
--- a/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.rs2asm
+++ b/runelite-client/src/main/scripts/ChatboxInputWidgetBuilder.rs2asm
@@ -47,7 +47,7 @@ LABEL23:
get_varbit 8119
iconst 1
if_icmpeq LABEL42
- jump LABEL184
+ jump LABEL201
LABEL42:
invoke 3160
iconst 1
@@ -127,11 +127,17 @@ LABEL96:
join_string 4
append
sstore 2
+ get_varc_string 335
+ invoke 1353
+ iconst 1
+ if_icmpeq LABEL109
+ jump LABEL121
+LABEL109:
iload 2
- iconst 80
- if_icmplt LABEL108
- jump LABEL115
-LABEL108:
+ iconst 79
+ if_icmplt LABEL113
+ jump LABEL120
+LABEL113:
sload 2
sload 0
sconst "*"
@@ -139,7 +145,22 @@ LABEL108:
join_string 3
append
sstore 2
-LABEL115:
+LABEL120:
+ jump LABEL132
+LABEL121:
+ iload 2
+ iconst 80
+ if_icmplt LABEL125
+ jump LABEL132
+LABEL125:
+ sload 2
+ sload 0
+ sconst "*"
+ sconst ""
+ join_string 3
+ append
+ sstore 2
+LABEL132:
sload 2
iconst 2147483647
iconst 495
@@ -147,9 +168,9 @@ LABEL115:
istore 3
iload 4
iconst 1
- if_icmpeq LABEL124
- jump LABEL141
-LABEL124:
+ if_icmpeq LABEL141
+ jump LABEL158
+LABEL141:
iconst 60
iconst 5
iload 3
@@ -166,8 +187,8 @@ LABEL124:
iconst 2
iconst 10616868
if_setposition
- jump LABEL153
-LABEL141:
+ jump LABEL170
+LABEL158:
iconst 0
iconst 30
iconst 0
@@ -180,26 +201,26 @@ LABEL141:
iconst 2
iconst 10616868
if_setposition
-LABEL153:
+LABEL170:
iload 3
iconst 10616887
if_getwidth
- if_icmpgt LABEL158
- jump LABEL164
-LABEL158:
+ if_icmpgt LABEL175
+ jump LABEL181
+LABEL175:
iconst 2
iconst 2
iconst 0
iconst 10616887
if_settextalign
- jump LABEL169
-LABEL164:
+ jump LABEL186
+LABEL181:
iconst 0
iconst 2
iconst 0
iconst 10616887
if_settextalign
-LABEL169:
+LABEL186:
iconst 10616887
if_clearops
iconst -1
@@ -214,19 +235,19 @@ LABEL169:
sconst ""
iconst 10616887
if_setonop
- jump LABEL234
-LABEL184:
+ jump LABEL251
+LABEL201:
invoke 3160
iconst 1
- if_icmpeq LABEL188
- jump LABEL193
-LABEL188:
+ if_icmpeq LABEL205
+ jump LABEL210
+LABEL205:
sconst "
"
sconst " You must set a name before you can chat."
join_string 2
sstore 2
- jump LABEL201
-LABEL193:
+ jump LABEL218
+LABEL210:
iconst 105
iconst 115
iconst 1894
@@ -235,7 +256,7 @@ LABEL193:
sconst " You must set a name before you can chat."
join_string 2
sstore 2
-LABEL201:
+LABEL218:
iconst 1
iconst 2
iconst 0
@@ -269,7 +290,7 @@ LABEL201:
sconst "ii"
iconst 10616887
if_setonop
-LABEL234:
+LABEL251:
sload 2
iconst 10616887
if_settext
diff --git a/runelite-client/src/main/scripts/CommandScript.hash b/runelite-client/src/main/scripts/CommandScript.hash
index b6795bca51..7a201bd5cb 100644
--- a/runelite-client/src/main/scripts/CommandScript.hash
+++ b/runelite-client/src/main/scripts/CommandScript.hash
@@ -1 +1 @@
-7A4628DC7933B4340CEC5F1B3C75ED1857FEDB5E683829499A07E5C364F633FA
\ No newline at end of file
+9B38CB6BF195C49B10D856C5F571AFDEC7BBEF96A4E3532F5B23E9341066144C
\ No newline at end of file
diff --git a/runelite-client/src/main/scripts/CommandScript.rs2asm b/runelite-client/src/main/scripts/CommandScript.rs2asm
index 1e345c3c41..e56d68fcec 100644
--- a/runelite-client/src/main/scripts/CommandScript.rs2asm
+++ b/runelite-client/src/main/scripts/CommandScript.rs2asm
@@ -90,13 +90,13 @@ LABEL60:
iload 0
iconst 84
if_icmpeq LABEL76
- jump LABEL829
+ jump LABEL822
LABEL76:
invoke 1984
iload 2
iconst 0
if_icmpgt LABEL81
- jump LABEL828
+ jump LABEL821
LABEL81:
iload 3
iconst 1
@@ -699,44 +699,39 @@ LABEL587:
sconst "You are not chatting as a guest in a clan channel at the moment."
mes
LABEL589:
- jump LABEL824
+ jump LABEL817
LABEL590:
iload 5
iconst 41
if_icmpeq LABEL594
- jump LABEL665
+ jump LABEL658
LABEL594:
iload 8
iconst 0
if_icmpeq LABEL598
- jump LABEL636
+ jump LABEL629
LABEL598:
iconst 0
activeclanchannel_find_affined
iconst 1
if_icmpeq LABEL603
- jump LABEL636
+ jump LABEL629
LABEL603:
- get_varbit 931
- iconst 0
- if_icmpeq LABEL607
- jump LABEL633
-LABEL607:
chat_playername
removetags
activeclanchannel_getuserslot
istore 7
iload 7
iconst -1
- if_icmpne LABEL615
- jump LABEL630
-LABEL615:
+ if_icmpne LABEL611
+ jump LABEL626
+LABEL611:
iload 7
activeclanchannel_getuserrank
activeclanchannel_getranktalk
- if_icmpge LABEL620
- jump LABEL630
-LABEL620:
+ if_icmpge LABEL616
+ jump LABEL626
+LABEL616:
get_varc_string 335
iload 6
iload 2
@@ -746,29 +741,24 @@ LABEL620:
iconst 0
iload 9
invoke 5517
- jump LABEL632
-LABEL630:
+ jump LABEL628
+LABEL626:
sconst "You do not have the required rank to talk in the clan's channel."
mes
-LABEL632:
- jump LABEL635
-LABEL633:
- sconst "You have muted your clan's channel. Unmute it if you wish to talk in it."
- mes
-LABEL635:
- jump LABEL664
-LABEL636:
+LABEL628:
+ jump LABEL657
+LABEL629:
iload 8
iconst 1
- if_icmpeq LABEL640
- jump LABEL655
-LABEL640:
+ if_icmpeq LABEL633
+ jump LABEL648
+LABEL633:
iconst 1
activeclanchannel_find_affined
iconst 1
- if_icmpeq LABEL645
- jump LABEL655
-LABEL645:
+ if_icmpeq LABEL638
+ jump LABEL648
+LABEL638:
get_varc_string 335
iload 6
iload 2
@@ -778,56 +768,56 @@ LABEL645:
iconst 0
iload 9
invoke 5517
- jump LABEL664
-LABEL655:
+ jump LABEL657
+LABEL648:
iload 8
iconst 1
- if_icmpeq LABEL659
- jump LABEL662
-LABEL659:
+ if_icmpeq LABEL652
+ jump LABEL655
+LABEL652:
sconst "You are not chatting in the channel of your Iron Group at the moment."
mes
- jump LABEL664
-LABEL662:
- sconst "You are not chatting in the channel of your own Iron Group at the moment."
+ jump LABEL657
+LABEL655:
+ sconst "You are not chatting in the channel of your Clan at the moment."
mes
-LABEL664:
- jump LABEL824
-LABEL665:
+LABEL657:
+ jump LABEL817
+LABEL658:
iload 5
iconst 9
- if_icmpeq LABEL669
- jump LABEL713
-LABEL669:
+ if_icmpeq LABEL662
+ jump LABEL706
+LABEL662:
clan_getchatcount
iconst 0
- if_icmpgt LABEL673
- jump LABEL706
-LABEL673:
+ if_icmpgt LABEL666
+ jump LABEL699
+LABEL666:
get_varbit 4394
iconst 1
- if_icmpeq LABEL677
- jump LABEL679
-LABEL677:
+ if_icmpeq LABEL670
+ jump LABEL672
+LABEL670:
clan_leavechat
- jump LABEL705
-LABEL679:
+ jump LABEL698
+LABEL672:
iload 6
iconst 1
- if_icmplt LABEL683
- jump LABEL688
-LABEL683:
+ if_icmplt LABEL676
+ jump LABEL681
+LABEL676:
sconst "/"
get_varc_string 335
append
set_varc_string 335
- jump LABEL699
-LABEL688:
+ jump LABEL692
+LABEL681:
iload 6
iconst 3
- if_icmpge LABEL692
- jump LABEL699
-LABEL692:
+ if_icmpge LABEL685
+ jump LABEL692
+LABEL685:
sconst "/"
get_varc_string 335
iload 6
@@ -835,30 +825,30 @@ LABEL692:
substring
append
set_varc_string 335
-LABEL699:
+LABEL692:
get_varc_string 335
iconst 2
iconst -1
iconst 0
iload 9
invoke 5517
-LABEL705:
- jump LABEL712
-LABEL706:
+LABEL698:
+ jump LABEL705
+LABEL699:
get_varc_string 335
iconst 0
iconst -1
iconst 0
iconst -1
invoke 5517
-LABEL712:
- jump LABEL824
-LABEL713:
+LABEL705:
+ jump LABEL817
+LABEL706:
iload 5
iconst 2
- if_icmpeq LABEL717
- jump LABEL727
-LABEL717:
+ if_icmpeq LABEL710
+ jump LABEL720
+LABEL710:
get_varc_string 335
iload 6
iload 2
@@ -868,98 +858,98 @@ LABEL717:
iconst 0
iload 9
invoke 5517
- jump LABEL824
-LABEL727:
+ jump LABEL817
+LABEL720:
iload 4
iconst 1
- if_icmpeq LABEL731
- jump LABEL818
-LABEL731:
+ if_icmpeq LABEL724
+ jump LABEL811
+LABEL724:
iload 2
iconst 2
- if_icmpgt LABEL735
- jump LABEL811
-LABEL735:
+ if_icmpgt LABEL728
+ jump LABEL804
+LABEL728:
get_varc_string 335
sconst "::toggleroof"
iconst 0
string_indexof_string
iconst 0
- if_icmpeq LABEL742
- jump LABEL770
-LABEL742:
+ if_icmpeq LABEL735
+ jump LABEL763
+LABEL735:
getremoveroofs
iconst 1
- if_icmpeq LABEL746
- jump LABEL758
-LABEL746:
+ if_icmpeq LABEL739
+ jump LABEL751
+LABEL739:
iconst 0
setremoveroofs
get_varbit 12378
iconst 0
- if_icmpeq LABEL752
- jump LABEL755
-LABEL752:
+ if_icmpeq LABEL745
+ jump LABEL748
+LABEL745:
sconst "Roofs will only be removed selectively."
mes
- jump LABEL757
-LABEL755:
+ jump LABEL750
+LABEL748:
sconst "Roofs will only be removed selectively. This setting will not be saved."
mes
-LABEL757:
- jump LABEL769
-LABEL758:
+LABEL750:
+ jump LABEL762
+LABEL751:
iconst 1
setremoveroofs
get_varbit 12378
iconst 1
- if_icmpeq LABEL764
- jump LABEL767
-LABEL764:
+ if_icmpeq LABEL757
+ jump LABEL760
+LABEL757:
sconst "Roofs are now all hidden."
mes
- jump LABEL769
-LABEL767:
+ jump LABEL762
+LABEL760:
sconst "Roofs are now all hidden. This setting will not be saved."
mes
-LABEL769:
- jump LABEL810
-LABEL770:
+LABEL762:
+ jump LABEL803
+LABEL763:
get_varc_string 335
sconst "::wiki "
iconst 0
string_indexof_string
iconst 0
- if_icmpeq LABEL782
+ if_icmpeq LABEL775
get_varc_string 335
sconst "::wiki"
compare
iconst 0
- if_icmpeq LABEL782
+ if_icmpeq LABEL775
sconst "runeliteCommand" ; load callback name
runelite_callback ; invoke callback
- jump LABEL785
-LABEL782:
+ jump LABEL778
+LABEL775:
get_varc_string 335
invoke 3299
- jump LABEL810
-LABEL785:
+ jump LABEL803
+LABEL778:
get_varc_string 335
sconst "::bank"
iconst 0
string_indexof_string
iconst 0
- if_icmpeq LABEL792
- jump LABEL799
-LABEL792:
+ if_icmpeq LABEL785
+ jump LABEL792
+LABEL785:
sconst "Hey, everyone, I just tried to do something very silly!"
iconst 0
iconst -1
iconst 0
iconst -1
invoke 5517
- jump LABEL810
-LABEL799:
+ jump LABEL803
+LABEL792:
get_varc_string 335
invoke 224
set_varc_string 335
@@ -971,97 +961,97 @@ LABEL799:
iload 2
substring
docheat
+LABEL803:
+ jump LABEL810
+LABEL804:
+ get_varc_string 335
+ iconst 0
+ iconst -1
+ iconst 0
+ iconst -1
+ invoke 5517
LABEL810:
jump LABEL817
LABEL811:
- get_varc_string 335
- iconst 0
- iconst -1
- iconst 0
- iconst -1
- invoke 5517
-LABEL817:
- jump LABEL824
-LABEL818:
get_varc_string 335
iconst 0
iconst -1
iconst 1
iload 9
invoke 5517
-LABEL824:
+LABEL817:
get_varc_string 335
invoke 77
sconst ""
set_varc_string 335
-LABEL828:
- jump LABEL904
-LABEL829:
+LABEL821:
+ jump LABEL897
+LABEL822:
iload 0
iconst 104
- if_icmpeq LABEL833
- jump LABEL839
-LABEL833:
+ if_icmpeq LABEL826
+ jump LABEL832
+LABEL826:
iload 3
iconst 1
- if_icmpeq LABEL837
- jump LABEL838
-LABEL837:
+ if_icmpeq LABEL830
+ jump LABEL831
+LABEL830:
invoke 75
-LABEL838:
- jump LABEL904
-LABEL839:
+LABEL831:
+ jump LABEL897
+LABEL832:
iload 0
iconst 105
- if_icmpeq LABEL843
- jump LABEL849
-LABEL843:
+ if_icmpeq LABEL836
+ jump LABEL842
+LABEL836:
iload 3
iconst 1
- if_icmpeq LABEL847
- jump LABEL848
-LABEL847:
+ if_icmpeq LABEL840
+ jump LABEL841
+LABEL840:
invoke 76
-LABEL848:
- jump LABEL904
-LABEL849:
+LABEL841:
+ jump LABEL897
+LABEL842:
iload 0
iconst 80
- if_icmpeq LABEL853
- jump LABEL898
-LABEL853:
+ if_icmpeq LABEL846
+ jump LABEL891
+LABEL846:
iconst 40697936
iconst 1
cc_find
iconst 1
- if_icmpeq LABEL859
- jump LABEL860
-LABEL859:
+ if_icmpeq LABEL852
+ jump LABEL853
+LABEL852:
return
-LABEL860:
+LABEL853:
get_varc_string 356
string_length
iconst 0
- if_icmpgt LABEL865
- jump LABEL885
-LABEL865:
+ if_icmpgt LABEL858
+ jump LABEL878
+LABEL858:
get_varc_string 356
friend_test
iconst 1
- if_icmpeq LABEL870
- jump LABEL873
-LABEL870:
+ if_icmpeq LABEL863
+ jump LABEL866
+LABEL863:
get_varc_string 356
invoke 107
return
-LABEL873:
+LABEL866:
get_varc_int 60
clientclock
- if_icmpgt LABEL877
- jump LABEL878
-LABEL877:
+ if_icmpgt LABEL870
+ jump LABEL871
+LABEL870:
return
-LABEL878:
+LABEL871:
clientclock
iconst 50
add
@@ -1069,14 +1059,14 @@ LABEL878:
sconst "That player was not found on your Friends list."
mes
return
-LABEL885:
+LABEL878:
get_varc_int 60
clientclock
- if_icmpgt LABEL889
- jump LABEL890
-LABEL889:
+ if_icmpgt LABEL882
+ jump LABEL883
+LABEL882:
return
-LABEL890:
+LABEL883:
clientclock
iconst 50
add
@@ -1084,8 +1074,8 @@ LABEL890:
sconst "You haven't received any messages to which you can reply."
mes
return
- jump LABEL904
-LABEL898:
+ jump LABEL897
+LABEL891:
get_varc_string 335
iconst 0
iload 0
@@ -1097,9 +1087,9 @@ LABEL898:
runelite_callback ;
if_icmpeq SKIPSETVARC ; skip setting varc with input
set_varc_string 335
- jump LABEL904 ; jump over SKIPSETVARC
+ jump LABEL897 ; jump over SKIPSETVARC
SKIPSETVARC:
pop_string ; pop message
-LABEL904:
+LABEL897:
invoke 223
return