diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index 12dc9b068c..aca0d2ac66 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -44,6 +44,7 @@ public final class AnimationID public static final int WOODCUTTING_DRAGON = 2846; public static final int WOODCUTTING_INFERNAL = 2117; public static final int WOODCUTTING_3A_AXE = 7264; + public static final int WOODCUTTING_CRYSTAL = 8324; public static final int CONSUMING = 829; // consuming consumables public static final int FIREMAKING = 733; public static final int DEATH = 836; @@ -94,6 +95,7 @@ public final class AnimationID public static final int FISHING_BARBTAIL_HARPOON = 5108; public static final int FISHING_DRAGON_HARPOON = 7401; public static final int FISHING_INFERNAL_HARPOON = 7402; + public static final int FISHING_CRYSTAL_HARPOON = 8336; public static final int FISHING_OILY_ROD = 622; public static final int FISHING_KARAMBWAN = 1193; public static final int FISHING_CRUSHING_INFERNAL_EELS = 7553; @@ -107,9 +109,11 @@ public final class AnimationID public static final int MINING_ADAMANT_PICKAXE = 628; public static final int MINING_RUNE_PICKAXE = 624; public static final int MINING_DRAGON_PICKAXE = 7139; - public static final int MINING_DRAGON_PICKAXE_ORN = 642; + public static final int MINING_DRAGON_PICKAXE_UPGRADED = 642; + public static final int MINING_DRAGON_PICKAXE_OR = 8346; public static final int MINING_INFERNAL_PICKAXE = 4482; public static final int MINING_3A_PICKAXE = 7283; + public static final int MINING_CRYSTAL_PICKAXE = 8347; public static final int MINING_MOTHERLODE_BRONZE = 6753; public static final int MINING_MOTHERLODE_IRON = 6754; public static final int MINING_MOTHERLODE_STEEL = 6755; @@ -118,9 +122,11 @@ public final class AnimationID public static final int MINING_MOTHERLODE_ADAMANT = 6756; public static final int MINING_MOTHERLODE_RUNE = 6752; public static final int MINING_MOTHERLODE_DRAGON = 6758; - public static final int MINING_MOTHERLODE_DRAGON_ORN = 335; + public static final int MINING_MOTHERLODE_DRAGON_UPGRADED = 335; + public static final int MINING_MOTHERLODE_DRAGON_OR = 8344; public static final int MINING_MOTHERLODE_INFERNAL = 4481; public static final int MINING_MOTHERLODE_3A = 7282; + public static final int MINING_MOTHERLODE_CRYSTAL = 8345; public static final int DENSE_ESSENCE_CHIPPING = 7201; public static final int DENSE_ESSENCE_CHISELING = 7202; public static final int HERBLORE_POTIONMAKING = 363; //used for both herb and secondary diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index 80988d8df5..6649cdc977 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -91,8 +91,8 @@ public class ChatCommandsPlugin extends Plugin private static final Pattern RAIDS_PATTERN = Pattern.compile("Your completed (.+) count is: (\\d+)"); private static final Pattern WINTERTODT_PATTERN = Pattern.compile("Your subdued Wintertodt count is: (\\d+)"); private static final Pattern BARROWS_PATTERN = Pattern.compile("Your Barrows chest count is: (\\d+)"); - private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?:Fight|Lap) duration: [0-9:]+. Personal best: ([0-9:]+)"); - private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?:Fight|Lap) duration: ([0-9:]+) \\(new personal best\\)"); + private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: [0-9:]+\\. Personal best: ([0-9:]+)"); + private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: ([0-9:]+) \\(new personal best\\)"); private static final Pattern DUEL_ARENA_WINS_PATTERN = Pattern.compile("You (were defeated|won)! You have(?: now)? won (\\d+) duels?"); private static final Pattern DUEL_ARENA_LOSSES_PATTERN = Pattern.compile("You have(?: now)? lost (\\d+) duels?"); private static final String TOTAL_LEVEL_COMMAND_STRING = "!total"; @@ -113,6 +113,7 @@ public class ChatCommandsPlugin extends Plugin private boolean logKills; private HiscoreEndpoint hiscoreEndpoint; // hiscore endpoint for current player private String lastBossKill; + private int lastPb = -1; @Inject private Client client; @@ -244,7 +245,17 @@ public class ChatCommandsPlugin extends Plugin int kc = Integer.parseInt(matcher.group(2)); setKc(boss, kc); - lastBossKill = boss; + // We either already have the pb, or need to remember the boss for the upcoming pb + if (lastPb > -1) + { + log.debug("Got out-of-order personal best for {}: {}", boss, lastPb); + setPb(boss, lastPb); + lastPb = -1; + } + else + { + lastBossKill = boss; + } return; } @@ -312,19 +323,16 @@ public class ChatCommandsPlugin extends Plugin setKc("Barrows Chests", kc); } - if (lastBossKill != null) + matcher = KILL_DURATION_PATTERN.matcher(message); + if (matcher.find()) { - matcher = KILL_DURATION_PATTERN.matcher(message); - if (matcher.find()) - { - matchPb(matcher); - } + matchPb(matcher); + } - matcher = NEW_PB_PATTERN.matcher(message); - if (matcher.find()) - { - matchPb(matcher); - } + matcher = NEW_PB_PATTERN.matcher(message); + if (matcher.find()) + { + matchPb(matcher); } lastBossKill = null; @@ -337,8 +345,19 @@ public class ChatCommandsPlugin extends Plugin if (s.length == 2) { int seconds = Integer.parseInt(s[0]) * 60 + Integer.parseInt(s[1]); - log.debug("Got personal best for {}: {}", lastBossKill, seconds); - setPb(lastBossKill, seconds); + if (lastBossKill != null) + { + // Most bosses sent boss kill message, and then pb message, so we + // use the remembered lastBossKill + log.debug("Got personal best for {}: {}", lastBossKill, seconds); + setPb(lastBossKill, seconds); + lastPb = -1; + } + else + { + // Some bosses send the pb message, and then the kill message! + lastPb = seconds; + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java index ea63fe7136..7e78d776f1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordGameEventType.java @@ -84,71 +84,74 @@ enum DiscordGameEventType BOSS_SMOKE_DEVIL("Thermonuclear smoke devil", DiscordAreaType.BOSSES, 9363, 9619), BOSS_VORKATH("Vorkath", DiscordAreaType.BOSSES, 9023), BOSS_WINTERTODT("Wintertodt", DiscordAreaType.BOSSES, 6462), + BOSS_ZALCANO("Zalcano", DiscordAreaType.BOSSES, 13250), BOSS_ZULRAH("Zulrah", DiscordAreaType.BOSSES, 9007), // Cities - CITY_AL_KHARID("Al Kharid", DiscordAreaType.CITIES, 13105, 13106), - CITY_APE_ATOLL("Ape Atoll", DiscordAreaType.CITIES, 10795, 11051, 10974, 11050), - CITY_ARCEUUS_HOUSE("Arceuus", DiscordAreaType.CITIES, 6459, 6715, 6458, 6714), - CITY_ARDOUGNE("Ardougne", DiscordAreaType.CITIES, 10548, 10547, 10292, 10291, 10036, 10035, 9780, 9779), - CITY_BARBARIAN_VILLAGE("Barbarian Village", DiscordAreaType.CITIES, 12341), - CITY_BANDIT_CAMP("Bandit Camp", DiscordAreaType.CITIES, 12591), - CITY_BEDABIN_CAMP("Bedabin Camp", DiscordAreaType.CITIES, 12590), - CITY_BRIMHAVEN("Brimhaven", DiscordAreaType.CITIES, 11057, 11058), - CITY_BURGH_DE_ROTT("Burgh de Rott", DiscordAreaType.CITIES, 13874, 13873, 14130, 14129), - CITY_BURTHORPE("Burthorpe", DiscordAreaType.CITIES, 11319, 11575), - CITY_CANIFIS("Canifis", DiscordAreaType.CITIES, 13878), - CITY_CATHERBY("Catherby", DiscordAreaType.CITIES, 11317, 11318, 11061), - CITY_CORSAIR_CAVE("Corsair Cove", DiscordAreaType.CITIES, 10028, 10284), - CITY_DORGESH_KAAN("Dorgesh-Kaan", DiscordAreaType.CITIES, 10835, 10834), - CITY_DRAYNOR("Draynor", DiscordAreaType.CITIES, 12338), - CITY_EDGEVILLE("Edgeville", DiscordAreaType.CITIES, 12342), - CITY_ENTRANA("Entrana", DiscordAreaType.CITIES, 11060, 11316), - CITY_FALADOR("Falador", DiscordAreaType.CITIES, 11828, 11572, 11571, 11827, 12084), - CITY_GOBLIN_VILLAGE("Goblin Village", DiscordAreaType.CITIES, 11830), - CITY_GUTANOTH("Gu'Tanoth", DiscordAreaType.CITIES, 10031), - CITY_HOSIDIUS_HOUSE("Hosidius", DiscordAreaType.CITIES, 6713, 6712, 6455, 6711, 6710, 6965, 6966, 7222, 7223, 6967), - CITY_JATISZO("Jatizso", DiscordAreaType.CITIES, 9531), - CITY_JIGGIG("Jiggig", DiscordAreaType.CITIES, 9775), - CITY_KARAMJA("Karamja", DiscordAreaType.CITIES, 11569, 11568, 11567, 11566, 11313, 11312, 11311), - CITY_KELDAGRIM("Keldagrim", DiscordAreaType.CITIES, 11423, 11422, 11679, 11678), - CITY_LLETYA("Lletya", DiscordAreaType.CITIES, 9265), - CITY_LOVAKENGJ_HOUSE("Lovakengj", DiscordAreaType.CITIES, 5692, 5948, 5691, 5947, 6203, 6202, 5690, 5946), - CITY_LUMBRIDGE("Lumbridge", DiscordAreaType.CITIES, 12850), - CITY_LUNAR_ISLE("Lunar Isle", DiscordAreaType.CITIES, 8253, 8252, 8509, 8508), - CITY_MEIYERDITCH("Meiyerditch", DiscordAreaType.CITIES, 14132, 14388, 14387, 14386, 14385), - CITY_MISCELLANIA("Miscellania", DiscordAreaType.CITIES, 10044, 10300), - CITY_MOS_LE_HARMLESS("Mos Le'Harmless", DiscordAreaType.CITIES, 14638), - CITY_MORTTON("Mort'ton", DiscordAreaType.CITIES, 13875), - CITY_MOR_UI_REK("Mor UI Rek", DiscordAreaType.CITIES, 9808, 9807, 10064, 10063), + CITY_AL_KHARID("Al Kharid" , DiscordAreaType.CITIES, 13105, 13106), + CITY_APE_ATOLL("Ape Atoll" , DiscordAreaType.CITIES, 10795, 11051, 10974, 11050), + CITY_ARCEUUS_HOUSE("Arceuus" , DiscordAreaType.CITIES, 6459, 6715, 6458, 6714), + CITY_ARDOUGNE("Ardougne" , DiscordAreaType.CITIES, 10548, 10547, 10292, 10291, 10036, 10035, 9780, 9779), + CITY_BARBARIAN_VILLAGE("Barbarian Village" , DiscordAreaType.CITIES, 12341), + CITY_BANDIT_CAMP("Bandit Camp" , DiscordAreaType.CITIES, 12591), + CITY_BEDABIN_CAMP("Bedabin Camp" , DiscordAreaType.CITIES, 12590), + CITY_BRIMHAVEN("Brimhaven" , DiscordAreaType.CITIES, 11057, 11058), + CITY_BURGH_DE_ROTT("Burgh de Rott" , DiscordAreaType.CITIES, 13874, 13873, 14130, 14129), + CITY_BURTHORPE("Burthorpe" , DiscordAreaType.CITIES, 11319, 11575), + CITY_CANIFIS("Canifis" , DiscordAreaType.CITIES, 13878), + CITY_CATHERBY("Catherby" , DiscordAreaType.CITIES, 11317, 11318, 11061), + CITY_CORSAIR_CAVE("Corsair Cove" , DiscordAreaType.CITIES, 10028, 10284), + CITY_DORGESH_KAAN("Dorgesh-Kaan" , DiscordAreaType.CITIES, 10835, 10834), + CITY_DRAYNOR("Draynor" , DiscordAreaType.CITIES, 12338), + CITY_EDGEVILLE("Edgeville" , DiscordAreaType.CITIES, 12342), + CITY_ENTRANA("Entrana" , DiscordAreaType.CITIES, 11060, 11316), + CITY_FALADOR("Falador" , DiscordAreaType.CITIES, 11828, 11572, 11571, 11827, 12084), + CITY_GOBLIN_VILLAGE("Goblin Village" , DiscordAreaType.CITIES, 11830), + CITY_GUTANOTH("Gu'Tanoth" , DiscordAreaType.CITIES, 10031), + CITY_GWENITH("Gwenith", DiscordAreaType.CITIES, 8501, 8757, 9013), + CITY_HOSIDIUS_HOUSE("Hosidius" , DiscordAreaType.CITIES, 6713, 6712, 6455, 6711, 6710, 6965, 6966, 7222, 7223, 6967), + CITY_JATISZO("Jatizso" , DiscordAreaType.CITIES, 9531), + CITY_JIGGIG("Jiggig" , DiscordAreaType.CITIES, 9775), + CITY_KARAMJA("Karamja" , DiscordAreaType.CITIES, 11569, 11568, 11567, 11566, 11313, 11312, 11311), + CITY_KELDAGRIM("Keldagrim" , DiscordAreaType.CITIES, 11423, 11422, 11679, 11678), + CITY_LLETYA("Lletya" , DiscordAreaType.CITIES, 9265), + CITY_LOVAKENGJ_HOUSE("Lovakengj" , DiscordAreaType.CITIES, 5692, 5948, 5691, 5947, 6203, 6202, 5690, 5946), + CITY_LUMBRIDGE("Lumbridge" , DiscordAreaType.CITIES, 12850), + CITY_LUNAR_ISLE("Lunar Isle" , DiscordAreaType.CITIES, 8253, 8252, 8509, 8508), + CITY_MEIYERDITCH("Meiyerditch" , DiscordAreaType.CITIES, 14132, 14388, 14387, 14386, 14385), + CITY_MISCELLANIA("Miscellania" , DiscordAreaType.CITIES, 10044, 10300), + CITY_MOS_LE_HARMLESS("Mos Le'Harmless" , DiscordAreaType.CITIES, 14638), + CITY_MORTTON("Mort'ton" , DiscordAreaType.CITIES, 13875), + CITY_MOR_UI_REK("Mor UI Rek" , DiscordAreaType.CITIES, 9808, 9807, 10064, 10063), CITY_MOUNT_KARUULM("Mount Karuulm", DiscordAreaType.CITIES, 5179, 4923, 5180), - CITY_NARDAH("Nardah", DiscordAreaType.CITIES, 13613), - CITY_NEITIZNOT("Neitiznot", DiscordAreaType.CITIES, 9275), - CITY_PISCATORIS("Piscatoris", DiscordAreaType.CITIES, 9273), - CITY_POLLNIVNEACH("Pollnivneach", DiscordAreaType.CITIES, 13358), - CITY_PORT_KHAZARD("Port Khazard", DiscordAreaType.CITIES, 10545), - CITY_PORT_PHASMATYS("Port Phasmatys", DiscordAreaType.CITIES, 14646), - CITY_PORT_SARIM("Port Sarim", DiscordAreaType.CITIES, 12082), - CITY_PISCARILIUS_HOUSE("Port Piscarilius", DiscordAreaType.CITIES, 6971, 7227, 6970, 7226), - CITY_RELLEKKA("Rellekka", DiscordAreaType.CITIES, 10553), - CITY_RIMMINGTON("Rimmington", DiscordAreaType.CITIES, 11826, 11570), - CITY_SEERS_VILLAGE("Seers' Village", DiscordAreaType.CITIES, 10806), - CITY_SHAYZIEN_HOUSE("Shayzien", DiscordAreaType.CITIES, 5944, 5943, 6200, 6199, 5688), - CITY_SHILO_VILLAGE("Shilo Village", DiscordAreaType.CITIES, 11310), - CITY_SOPHANEM("Sophanem", DiscordAreaType.CITIES, 13099), - CITY_TAI_BWO_WANNAI("Tai Bwo Wannai", DiscordAreaType.CITIES, 11056, 11055), - CITY_TAVERLEY("Taverley", DiscordAreaType.CITIES, 11574, 11573), - CITY_TREE_GNOME_STRONGHOLD("Tree Gnome Stronghold", DiscordAreaType.CITIES, 9782, 9781), - CITY_TREE_GNOME_VILLAGE("Tree Gnome Village", DiscordAreaType.CITIES, 10033), - CITY_TROLL_STRONGHOLD("Troll Stronghold", DiscordAreaType.CITIES, 11321), - CITY_TYRAS_CAMP("Tyras Camp", DiscordAreaType.CITIES, 8753, 8752), - CITY_UZER("Uzer", DiscordAreaType.CITIES, 13872), - CITY_VARROCK("Varrock", DiscordAreaType.CITIES, 12596, 12597, 12598, 12852, 12853, 12854, 13108, 13109, 13110), - CITY_WITCHHAVEN("Witchaven", DiscordAreaType.CITIES, 10803), + CITY_NARDAH("Nardah" , DiscordAreaType.CITIES, 13613), + CITY_NEITIZNOT("Neitiznot" , DiscordAreaType.CITIES, 9275), + CITY_PISCATORIS("Piscatoris" , DiscordAreaType.CITIES, 9273), + CITY_POLLNIVNEACH("Pollnivneach" , DiscordAreaType.CITIES, 13358), + CITY_PORT_KHAZARD("Port Khazard" , DiscordAreaType.CITIES, 10545), + CITY_PORT_PHASMATYS("Port Phasmatys" , DiscordAreaType.CITIES, 14646), + CITY_PORT_SARIM("Port Sarim" , DiscordAreaType.CITIES, 12082), + CITY_PISCARILIUS_HOUSE("Port Piscarilius" , DiscordAreaType.CITIES, 6971, 7227, 6970, 7226), + CITY_PRIFDDINAS("Prifddinas", DiscordAreaType.CITIES, 12894, 12895, 13150, 13151), + CITY_RELLEKKA("Rellekka" , DiscordAreaType.CITIES, 10553), + CITY_RIMMINGTON("Rimmington" , DiscordAreaType.CITIES, 11826, 11570), + CITY_SEERS_VILLAGE("Seers' Village" , DiscordAreaType.CITIES, 10806), + CITY_SHAYZIEN_HOUSE("Shayzien" , DiscordAreaType.CITIES, 5944, 5943, 6200, 6199, 5688), + CITY_SHILO_VILLAGE("Shilo Village" , DiscordAreaType.CITIES, 11310), + CITY_SOPHANEM("Sophanem" , DiscordAreaType.CITIES, 13099), + CITY_TAI_BWO_WANNAI("Tai Bwo Wannai" , DiscordAreaType.CITIES, 11056, 11055), + CITY_TAVERLEY("Taverley" , DiscordAreaType.CITIES, 11574, 11573), + CITY_TREE_GNOME_STRONGHOLD("Tree Gnome Stronghold" , DiscordAreaType.CITIES, 9782, 9781), + CITY_TREE_GNOME_VILLAGE("Tree Gnome Village" , DiscordAreaType.CITIES, 10033), + CITY_TROLL_STRONGHOLD("Troll Stronghold" , DiscordAreaType.CITIES, 11321), + CITY_TYRAS_CAMP("Tyras Camp" , DiscordAreaType.CITIES, 8753, 8752), + CITY_UZER("Uzer" , DiscordAreaType.CITIES, 13872), + CITY_VARROCK("Varrock" , DiscordAreaType.CITIES, 12596, 12597, 12598, 12852, 12853, 12854, 13108, 13109, 13110), + CITY_WITCHHAVEN("Witchaven" , DiscordAreaType.CITIES, 10803), CITY_WOODCUTTING_GUILD("Woodcutting Guild", DiscordAreaType.CITIES, 6454, 6198, 6298), - CITY_YANILLE("Yanille", DiscordAreaType.CITIES, 10288, 10032), - CITY_ZANARIS("Zanaris", DiscordAreaType.CITIES, 9285, 9541, 9540, 9797), - CITY_ZULANDRA("Zul-Andra", DiscordAreaType.CITIES, 8751), + CITY_YANILLE("Yanille" , DiscordAreaType.CITIES, 10288, 10032), + CITY_ZANARIS("Zanaris" , DiscordAreaType.CITIES, 9285, 9541, 9540, 9797), + CITY_ZULANDRA("Zul-Andra" , DiscordAreaType.CITIES, 8751), // Dungeons DUNGEON_ABANDONED_MINE("Abandoned Mine", DiscordAreaType.DUNGEONS, 13718, 11079, 11078, 11077, 10823, 10822, 10821), @@ -180,6 +183,7 @@ enum DiscordGameEventType DUNGEON_GOBLIN_CAVE("Goblin Cave", DiscordAreaType.DUNGEONS, 10393), DUNGEON_GRAND_TREE_TUNNELS("Grand Tree Tunnels", DiscordAreaType.DUNGEONS, 9882), DUNGEON_HAM("H.A.M Dungeon", DiscordAreaType.DUNGEONS, 12694, 10321), + DUNGEON_IORWERTH("Iorwerth Dungeon", DiscordAreaType.DUNGEONS, 12738, 12993, 12994), DUNGEON_JATIZSO_MINES("Jatizo Mines", DiscordAreaType.DUNGEONS, 9631), DUNGEON_JIGGIG_BURIAL_TOMB("Jiggig Burial Tomb", DiscordAreaType.DUNGEONS, 9875, 9874), DUNGEON_JOGRE("Jogre Dungeon", DiscordAreaType.DUNGEONS, 11412), @@ -211,6 +215,7 @@ enum DiscordGameEventType DUNGEON_THE_WARRENS("The Warrens", DiscordAreaType.DUNGEONS, 7070, 7326), DUNGEON_TOLNA("Dungeon of Tolna", DiscordAreaType.DUNGEONS, 13209), DUNGEON_TOWER_OF_LIFE("Tower of Life Basement", DiscordAreaType.DUNGEONS, 12100), + DUNGEON_TRAHAEARN_MINE("Trahaearn Mine", DiscordAreaType.DUNGEONS, 13249), DUNGEON_TUNNEL_OF_CHAOS("Tunnel of Chaos", DiscordAreaType.DUNGEONS, 12625), DUNGEON_UNDERGROUND_PASS("Underground Pass", DiscordAreaType.DUNGEONS, 9369, 9370), DUNGEON_VARROCKSEWERS("Varrock Sewers", DiscordAreaType.DUNGEONS, 12954, 13210), @@ -232,6 +237,7 @@ enum DiscordGameEventType MG_CLAN_WARS("Clan Wars", DiscordAreaType.MINIGAMES, 13135, 13134, 13133, 13131, 13130, 13387, 13386), MG_DUEL_ARENA("Duel Arena", DiscordAreaType.MINIGAMES, 13362), MG_FISHING_TRAWLER("Fishing Trawler", DiscordAreaType.MINIGAMES, 7499), + MG_GAUNTLET("Gauntlet", DiscordAreaType.MINIGAMES, 12995), MG_INFERNO("The Inferno", DiscordAreaType.MINIGAMES, 9043), MG_LAST_MAN_STANDING("Last Man Standing", DiscordAreaType.MINIGAMES, 13660, 13659, 13658, 13916, 13915, 13914), MG_MAGE_TRAINING_ARENA("Mage Training Arena", DiscordAreaType.MINIGAMES, 13462, 13463), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java index 539c810de2..16922d9874 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsConfig.java @@ -68,15 +68,4 @@ public interface FpsConfig extends Config { return true; } - - @ConfigItem( - keyName = "drawPing", - name = "Draw ping indicator", - description = "Show a number in the corner for the current ping", - position = 3 - ) - default boolean drawPing() - { - return false; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsOverlay.java index 17afae61b6..0103337792 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsOverlay.java @@ -26,14 +26,14 @@ package net.runelite.client.plugins.fps; import java.awt.Color; import java.awt.Dimension; -import java.awt.FontMetrics; import java.awt.Graphics2D; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; import net.runelite.api.Point; -import net.runelite.api.Varbits; import net.runelite.api.events.FocusChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; @@ -51,6 +51,10 @@ import net.runelite.client.ui.overlay.OverlayUtil; @Singleton public class FpsOverlay extends Overlay { + private static final int Y_OFFSET = 1; + private static final int X_OFFSET = 1; + private static final String FPS_STRING = " FPS"; + // Local dependencies private final Client client; private final FpsPlugin plugin; @@ -84,62 +88,30 @@ public class FpsOverlay extends Overlay return isEnforced() ? Color.red : Color.yellow; } - private static Color getPingColor(int ping) - { - if (ping >= 100 || ping < 0) - { - return Color.red; - } - else if (ping >= 50) - { - return Color.yellow; - } - return Color.green; - } - - private int calculateOffset() - { - if ((client.getVar(Varbits.SIDE_PANELS) == 1) && client.isResized()) - { - return 27; - } - - return 2; - } - @Override public Dimension render(Graphics2D graphics) { - if (!plugin.isDrawFps() && !plugin.isDrawPing()) + if (!plugin.isDrawFps()) { return null; } - final int offset = calculateOffset(); + // On resizable bottom line mode the logout button is at the top right, so offset the overlay + // to account for it + Widget logoutButton = client.getWidget(WidgetInfo.RESIZABLE_MINIMAP_LOGOUT_BUTTON); + int xOffset = X_OFFSET; + if (logoutButton != null && !logoutButton.isHidden()) + { + xOffset += logoutButton.getWidth(); + } + + final String text = client.getFPS() + FPS_STRING; + final int textWidth = graphics.getFontMetrics().stringWidth(text); + final int textHeight = graphics.getFontMetrics().getAscent() - graphics.getFontMetrics().getDescent(); + final int width = (int) client.getRealDimensions().getWidth(); - final FontMetrics fontMetrics = graphics.getFontMetrics(); - - int baseYOffset = (fontMetrics.getAscent() - fontMetrics.getDescent()) + 1; - - if (plugin.isDrawFps()) - { - final String fpsText = String.format("%d FPS", client.getFPS()); - final int textWidth = fontMetrics.stringWidth(fpsText); - - final Point point = new Point(width - textWidth - offset, baseYOffset); - OverlayUtil.renderTextLocation(graphics, point, fpsText, getFpsValueColor()); - - baseYOffset += 11; - } - - if (plugin.isDrawPing()) - { - final String pingText = String.format("%dms", plugin.getPing()); - final int textWidth = fontMetrics.stringWidth(pingText); - - final Point point = new Point(width - textWidth - offset, baseYOffset); - OverlayUtil.renderTextLocation(graphics, point, pingText, getPingColor(plugin.getPing())); - } + final Point point = new Point(width - textWidth - xOffset, textHeight + Y_OFFSET); + OverlayUtil.renderTextLocation(graphics, point, text, getFpsValueColor()); return null; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsPlugin.java index b33699436a..4af5c588a8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsPlugin.java @@ -27,27 +27,19 @@ package net.runelite.client.plugins.fps; import com.google.inject.Inject; import com.google.inject.Provides; import com.google.inject.Singleton; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import lombok.AccessLevel; import lombok.Getter; -import net.runelite.api.Client; -import net.runelite.api.GameState; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.FocusChanged; -import net.runelite.api.events.GameStateChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.overlay.OverlayManager; -import net.runelite.client.util.ExecutorServiceExceptionLogger; -import net.runelite.client.util.ping.Ping; /** - * Performance has two primary areas, this plugin class just keeps those areas up to date and handles setup / teardown. + * FPS Control has two primary areas, this plugin class just keeps those areas up to date and handles setup / teardown. * *

Overlay paints the current FPS, the color depends on whether or not FPS is being enforced. * The overlay is lightweight and is merely and indicator. @@ -55,15 +47,11 @@ import net.runelite.client.util.ping.Ping; *

Draw Listener, sleeps a calculated amount after each canvas paint operation. * This is the heart of the plugin, the amount of sleep taken is regularly adjusted to account varying * game and system load, it usually finds the sweet spot in about two seconds. - * - *

Pinging the world, when logged in and ping display is enabled, every 5 seconds the remote server - * for the current world is pinged. A scheduled method in this class is responsible for that. When ping fails - * or those conditions are not met, ping will have the value of -1. */ @PluginDescriptor( name = "Performance", - description = "Show current Ping and FPS or set an FPS limit", - tags = {"frames", "framerate", "limit", "overlay", "ping"}, + description = "Show current FPS or set an FPS limit", + tags = {"frames", "framerate", "limit", "overlay"}, enabledByDefault = false ) @Singleton @@ -71,9 +59,6 @@ public class FpsPlugin extends Plugin { static final String CONFIG_GROUP_KEY = "fpscontrol"; - @Getter - private int ping; - @Inject private OverlayManager overlayManager; @@ -86,30 +71,18 @@ public class FpsPlugin extends Plugin @Inject private DrawManager drawManager; - @Inject - private Client client; - @Inject private FpsConfig fpsConfig; @Inject private EventBus eventBus; - private final ScheduledExecutorService pingExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()); - - private boolean loaded = false; - - private boolean shutdown; - @Getter(AccessLevel.PACKAGE) private FpsLimitMode limitMode; @Getter(AccessLevel.PACKAGE) private boolean drawFps; - @Getter(AccessLevel.PACKAGE) - private boolean drawPing; - @Provides FpsConfig provideConfig(ConfigManager configManager) { @@ -124,7 +97,6 @@ public class FpsPlugin extends Plugin limitMode = fpsConfig.limitMode(); drawFps = fpsConfig.drawFps(); - drawPing = fpsConfig.drawPing(); } } @@ -134,11 +106,6 @@ public class FpsPlugin extends Plugin overlay.onFocusChanged(event); } - private void onGameStateChanged(GameStateChanged event) - { - shutdown = event.getGameState() != GameState.LOGGED_IN; - } - @Override protected void startUp() throws Exception { @@ -146,17 +113,9 @@ public class FpsPlugin extends Plugin limitMode = fpsConfig.limitMode(); drawFps = fpsConfig.drawFps(); - drawPing = fpsConfig.drawPing(); overlayManager.add(overlay); drawManager.registerEveryFrameListener(drawListener); drawListener.reloadConfig(); - shutdown = client.getGameState() != GameState.LOGGED_IN; - - if (!loaded) - { - pingExecutorService.scheduleAtFixedRate(this::getPingToCurrentWorld, 5, 5, TimeUnit.SECONDS); - loaded = true; - } } @Override @@ -166,25 +125,11 @@ public class FpsPlugin extends Plugin overlayManager.remove(overlay); drawManager.unregisterEveryFrameListener(drawListener); - shutdown = true; } private void addSubscriptions() { eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged); eventBus.subscribe(FocusChanged.class, this, this::onFocusChanged); - eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); - } - - private void getPingToCurrentWorld() - { - if (!shutdown && drawPing) - { - ping = Ping.ping(String.format("oldschool%d.runescape.com", client.getWorld() - 300)); - } - else - { - ping = -1; - } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 09bc5ab850..5ce500c999 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -195,11 +195,12 @@ public class IdleNotifierPlugin extends Plugin case WOODCUTTING_DRAGON: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: - /* Cooking(Fire, Range) */ + case WOODCUTTING_CRYSTAL: + /* Cooking(Fire, Range) */ case COOKING_FIRE: case COOKING_RANGE: case COOKING_WINE: - /* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */ + /* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */ case GEM_CUTTING_OPAL: case GEM_CUTTING_JADE: case GEM_CUTTING_REDTOPAZ: @@ -214,7 +215,7 @@ public class IdleNotifierPlugin extends Plugin case CRAFTING_LEATHER: case CRAFTING_POTTERS_WHEEL: case CRAFTING_POTTERY_OVEN: - /* Fletching(Cutting, Stringing) */ + /* Fletching(Cutting, Stringing) */ case FLETCHING_BOW_CUTTING: case FLETCHING_STRING_NORMAL_SHORTBOW: case FLETCHING_STRING_OAK_SHORTBOW: @@ -228,11 +229,11 @@ public class IdleNotifierPlugin extends Plugin case FLETCHING_STRING_MAPLE_LONGBOW: case FLETCHING_STRING_YEW_LONGBOW: case FLETCHING_STRING_MAGIC_LONGBOW: - /* Smithing(Anvil, Furnace, Cannonballs */ + /* Smithing(Anvil, Furnace, Cannonballs */ case SMITHING_ANVIL: case SMITHING_SMELTING: case SMITHING_CANNONBALL: - /* Fishing */ + /* Fishing */ case FISHING_CRUSHING_INFERNAL_EELS: case FISHING_CUTTING_SACRED_EELS: case FISHING_BIG_NET: @@ -246,7 +247,7 @@ public class IdleNotifierPlugin extends Plugin case FISHING_OILY_ROD: case FISHING_KARAMBWAN: case FISHING_BAREHAND: - /* Mining(Normal) */ + /* Mining(Normal) */ case MINING_BRONZE_PICKAXE: case MINING_IRON_PICKAXE: case MINING_STEEL_PICKAXE: @@ -255,16 +256,32 @@ public class IdleNotifierPlugin extends Plugin case MINING_ADAMANT_PICKAXE: case MINING_RUNE_PICKAXE: case MINING_DRAGON_PICKAXE: - case MINING_DRAGON_PICKAXE_ORN: + case MINING_DRAGON_PICKAXE_UPGRADED: + case MINING_DRAGON_PICKAXE_OR: case MINING_INFERNAL_PICKAXE: case MINING_3A_PICKAXE: + case MINING_CRYSTAL_PICKAXE: case DENSE_ESSENCE_CHIPPING: case DENSE_ESSENCE_CHISELING: - /* Herblore */ + /* Mining(Motherlode) */ + case MINING_MOTHERLODE_BRONZE: + case MINING_MOTHERLODE_IRON: + case MINING_MOTHERLODE_STEEL: + case MINING_MOTHERLODE_BLACK: + case MINING_MOTHERLODE_MITHRIL: + case MINING_MOTHERLODE_ADAMANT: + case MINING_MOTHERLODE_RUNE: + case MINING_MOTHERLODE_DRAGON: + case MINING_MOTHERLODE_DRAGON_UPGRADED: + case MINING_MOTHERLODE_DRAGON_OR: + case MINING_MOTHERLODE_INFERNAL: + case MINING_MOTHERLODE_3A: + case MINING_MOTHERLODE_CRYSTAL: + /* Herblore */ case HERBLORE_PESTLE_AND_MORTAR: case HERBLORE_POTIONMAKING: case HERBLORE_MAKE_TAR: - /* Magic */ + /* Magic */ case MAGIC_CHARGING_ORBS: case MAGIC_LUNAR_PLANK_MAKE: case MAGIC_LUNAR_STRING_JEWELRY: @@ -273,16 +290,16 @@ public class IdleNotifierPlugin extends Plugin case MAGIC_ENCHANTING_AMULET_1: case MAGIC_ENCHANTING_AMULET_2: case MAGIC_ENCHANTING_AMULET_3: - /* Prayer */ + /* Prayer */ case USING_GILDED_ALTAR: - /* Farming */ + /* Farming */ case FARMING_MIX_ULTRACOMPOST: case FARMING_HARVEST_BUSH: case FARMING_HARVEST_HERB: case FARMING_HARVEST_FRUIT_TREE: case FARMING_HARVEST_FLOWER: case FARMING_HARVEST_ALLOTMENT: - /* Misc */ + /* Misc */ case PISCARILIUS_CRANE_REPAIR: case HOME_MAKE_TABLET: case SAND_COLLECTION: diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java index d71bcc0074..8d411a4aaa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java @@ -72,6 +72,7 @@ enum ItemIdentification MAGIC_SAPLING(Type.SAPLING, "Magic", "MAG", ItemID.MAGIC_SAPLING, ItemID.MAGIC_SEEDLING, ItemID.MAGIC_SEEDLING_W), REDWOOD_SAPLING(Type.SAPLING, "Red", "RED", ItemID.REDWOOD_SAPLING, ItemID.REDWOOD_SEEDLING, ItemID.REDWOOD_SEEDLING_W), SPIRIT_SAPLING(Type.SAPLING, "Spirit", "SPI", ItemID.SPIRIT_SAPLING, ItemID.SPIRIT_SEEDLING, ItemID.SPIRIT_SEEDLING_W), + CRYSTAL_SAPLING(Type.SAPLING, "Crystal", "CRY", ItemID.CRYSTAL_SAPLING, ItemID.CRYSTAL_SEEDLING, ItemID.CRYSTAL_SEEDLING_W), APPLE_SAPLING(Type.SAPLING, "Apple", "APP", ItemID.APPLE_SAPLING, ItemID.APPLE_SEEDLING, ItemID.APPLE_SEEDLING_W), BANANA_SAPLING(Type.SAPLING, "Banana", "BAN", ItemID.BANANA_SAPLING, ItemID.BANANA_SEEDLING, ItemID.BANANA_SEEDLING_W), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodePlugin.java index 880a74c8fe..c38ed61de1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/motherlode/MotherlodePlugin.java @@ -43,18 +43,7 @@ import javax.inject.Singleton; import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.AnimationID; -import static net.runelite.api.AnimationID.IDLE; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_3A; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_ADAMANT; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BLACK; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_BRONZE; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_DRAGON_ORN; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_INFERNAL; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_IRON; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_MITHRIL; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_RUNE; -import static net.runelite.api.AnimationID.MINING_MOTHERLODE_STEEL; +import static net.runelite.api.AnimationID.*; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.GameObject; @@ -451,7 +440,9 @@ public class MotherlodePlugin extends Plugin case MINING_MOTHERLODE_ADAMANT: case MINING_MOTHERLODE_RUNE: case MINING_MOTHERLODE_DRAGON: - case MINING_MOTHERLODE_DRAGON_ORN: + case MINING_MOTHERLODE_DRAGON_UPGRADED: + case MINING_MOTHERLODE_DRAGON_OR: + case MINING_MOTHERLODE_CRYSTAL: case MINING_MOTHERLODE_INFERNAL: case MINING_MOTHERLODE_3A: lastAnimation = animation; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java index 247b2f97ab..c13389485d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java @@ -102,14 +102,19 @@ class NightmareZoneOverlay extends Overlay renderAbsorptionCounter(); + final int currentPoints = client.getVar(Varbits.NMZ_POINTS); + final int totalPoints = currentPoints + client.getVar(VarPlayer.NMZ_REWARD_POINTS); + panelComponent.getChildren().clear(); + TableComponent tableComponent = new TableComponent(); tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT); - tableComponent.addRow("Points:", StackFormatter.formatNumber(client.getVar(Varbits.NMZ_POINTS))); + tableComponent.addRow("Points:", StackFormatter.formatNumber(currentPoints)); + tableComponent.addRow("Points/Hour:", StackFormatter.formatNumber(plugin.getPointsPerHour())); if (plugin.isShowtotalpoints()) { - tableComponent.addRow("Total:", StackFormatter.formatNumber(client.getVar(VarPlayer.NMZ_REWARD_POINTS) + client.getVar(Varbits.NMZ_POINTS))); + tableComponent.addRow("Total:", StackFormatter.formatNumber(totalPoints)); } panelComponent.getChildren().add(tableComponent); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java index 9c32dabc51..7993ae37ca 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java @@ -25,11 +25,14 @@ package net.runelite.client.plugins.nightmarezone; import com.google.inject.Provides; + import java.awt.Color; import java.util.Arrays; import javax.inject.Inject; import javax.inject.Singleton; import lombok.AccessLevel; +import java.time.Duration; +import java.time.Instant; import lombok.Getter; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; @@ -56,6 +59,7 @@ import net.runelite.client.util.Text; public class NightmareZonePlugin extends Plugin { private static final int[] NMZ_MAP_REGION = {9033}; + private static final Duration HOUR = Duration.ofHours(1); @Inject private Notifier notifier; @@ -75,6 +79,11 @@ public class NightmareZonePlugin extends Plugin @Inject private EventBus eventBus; + @Getter + private int pointsPerHour; + + private Instant nmzSessionStartTime; + // This starts as true since you need to get // above the threshold before sending notifications private boolean absorptionNotificationSend = true; @@ -120,6 +129,8 @@ public class NightmareZonePlugin extends Plugin { nmzWidget.setHidden(false); } + + resetPointsPerHour(); } private void addSubscriptions() @@ -155,6 +166,11 @@ public class NightmareZonePlugin extends Plugin absorptionNotificationSend = true; } + if (nmzSessionStartTime != null) + { + resetPointsPerHour(); + } + return; } @@ -162,6 +178,11 @@ public class NightmareZonePlugin extends Plugin { checkAbsorption(); } + + if (config.moveOverlay()) + { + pointsPerHour = calculatePointsPerHour(); + } } private void onChatMessage(ChatMessage event) @@ -239,6 +260,32 @@ public class NightmareZonePlugin extends Plugin return !Arrays.equals(client.getMapRegions(), NMZ_MAP_REGION); } + private int calculatePointsPerHour() + { + Instant now = Instant.now(); + final int currentPoints = client.getVar(Varbits.NMZ_POINTS); + + if (nmzSessionStartTime == null) + { + nmzSessionStartTime = now; + } + + Duration timeSinceStart = Duration.between(nmzSessionStartTime, now); + + if (!timeSinceStart.isZero()) + { + return (int) ((double) currentPoints * (double) HOUR.toMillis() / (double) timeSinceStart.toMillis()); + } + + return 0; + } + + private void resetPointsPerHour() + { + nmzSessionStartTime = null; + pointsPerHour = 0; + } + private void updateConfig() { this.moveOverlay = config.moveOverlay(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java index b98fe9fdc6..6e0a086f05 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wintertodt/WintertodtPlugin.java @@ -453,6 +453,7 @@ public class WintertodtPlugin extends Plugin case WOODCUTTING_DRAGON: case WOODCUTTING_INFERNAL: case WOODCUTTING_3A_AXE: + case WOODCUTTING_CRYSTAL: setActivity(WintertodtActivity.WOODCUTTING); break; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java index 709ea85378..dfdf86f6f4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/woodcutting/Axe.java @@ -33,6 +33,7 @@ import static net.runelite.api.AnimationID.WOODCUTTING_3A_AXE; import static net.runelite.api.AnimationID.WOODCUTTING_ADAMANT; import static net.runelite.api.AnimationID.WOODCUTTING_BLACK; import static net.runelite.api.AnimationID.WOODCUTTING_BRONZE; +import static net.runelite.api.AnimationID.WOODCUTTING_CRYSTAL; import static net.runelite.api.AnimationID.WOODCUTTING_DRAGON; import static net.runelite.api.AnimationID.WOODCUTTING_INFERNAL; import static net.runelite.api.AnimationID.WOODCUTTING_IRON; @@ -42,6 +43,7 @@ import static net.runelite.api.AnimationID.WOODCUTTING_STEEL; import static net.runelite.api.ItemID.ADAMANT_AXE; import static net.runelite.api.ItemID.BLACK_AXE; import static net.runelite.api.ItemID.BRONZE_AXE; +import static net.runelite.api.ItemID.CRYSTAL_AXE; import static net.runelite.api.ItemID.DRAGON_AXE; import static net.runelite.api.ItemID.INFERNAL_AXE; import static net.runelite.api.ItemID.IRON_AXE; @@ -63,7 +65,8 @@ enum Axe RUNE(WOODCUTTING_RUNE, RUNE_AXE), DRAGON(WOODCUTTING_DRAGON, DRAGON_AXE), INFERNAL(WOODCUTTING_INFERNAL, INFERNAL_AXE), - THIRDAGE(WOODCUTTING_3A_AXE, _3RD_AGE_AXE); + THIRDAGE(WOODCUTTING_3A_AXE, _3RD_AGE_AXE), + CRYSTAL(WOODCUTTING_CRYSTAL, CRYSTAL_AXE); private final Integer animId; private final Integer itemId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java index 8035af73fb..d21ed61e80 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperConfig.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Lotto + * Copyright (c) 2019, gregg1494 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,4 +124,15 @@ public interface WorldHopperConfig extends Config { return SubscriptionFilterMode.BOTH; } + + @ConfigItem( + keyName = "displayPing", + name = "Display current ping", + description = "Displays ping to current game world", + position = 7 + ) + default boolean displayPing() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPingOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPingOverlay.java new file mode 100644 index 0000000000..1839b14ddd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPingOverlay.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019, gregg1494 + * 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.worldhopper; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +class WorldHopperPingOverlay extends Overlay +{ + private static final int Y_OFFSET = 11; + private static final int X_OFFSET = 1; + + private final Client client; + private final WorldHopperPlugin worldHopperPlugin; + + @Inject + private WorldHopperPingOverlay(Client client, WorldHopperPlugin worldHopperPlugin) + { + this.client = client; + this.worldHopperPlugin = worldHopperPlugin; + setLayer(OverlayLayer.ABOVE_WIDGETS); + setPriority(OverlayPriority.HIGH); + setPosition(OverlayPosition.DYNAMIC); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!worldHopperPlugin.isDisplayPing()) + { + return null; + } + + final int ping = worldHopperPlugin.getCurrentPing(); + if (ping < 0) + { + return null; + } + + final String text = ping + " ms"; + final int textWidth = graphics.getFontMetrics().stringWidth(text); + final int textHeight = graphics.getFontMetrics().getAscent() - graphics.getFontMetrics().getDescent(); + + // Adjust ping offset for logout button + Widget logoutButton = client.getWidget(WidgetInfo.RESIZABLE_MINIMAP_LOGOUT_BUTTON); + int xOffset = X_OFFSET; + if (logoutButton != null && !logoutButton.isHidden()) + { + xOffset += logoutButton.getWidth(); + } + + final int width = (int) client.getRealDimensions().getWidth(); + final Point point = new Point(width - textWidth - xOffset, textHeight + Y_OFFSET); + OverlayUtil.renderTextLocation(graphics, point, text, Color.YELLOW); + + return null; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java index 8513a87814..1b232678b3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldhopper/WorldHopperPlugin.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2017, Adam * Copyright (c) 2018, Lotto + * Copyright (c) 2019, gregg1494 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +47,7 @@ import javax.imageio.ImageIO; import javax.inject.Inject; import javax.inject.Singleton; import javax.swing.SwingUtilities; +import lombok.AccessLevel; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; @@ -78,6 +80,7 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.client.util.HotkeyListener; import net.runelite.client.util.Text; @@ -98,8 +101,7 @@ import org.apache.commons.lang3.ArrayUtils; public class WorldHopperPlugin extends Plugin { private static final int WORLD_FETCH_TIMER = 10; - private static final int WORLD_PING_TIMER = 10; - private static final int REFRESH_THROTTLE = 60_000; // ms + private static final int REFRESH_THROTTLE = 60_000; // ms private static final int TICK_THROTTLE = (int) Duration.ofMinutes(10).toMillis(); private static final int DISPLAY_SWITCHER_MAX_ATTEMPTS = 3; @@ -133,6 +135,12 @@ public class WorldHopperPlugin extends Plugin @Inject private EventBus eventBus; + @Inject + private OverlayManager overlayManager; + + @Inject + private WorldHopperPingOverlay worldHopperOverlay; + private ScheduledExecutorService hopperExecutorService; private NavigationButton navButton; @@ -146,8 +154,9 @@ public class WorldHopperPlugin extends Plugin private int favoriteWorld1, favoriteWorld2; - private ScheduledFuture worldResultFuture, pingFuture; + private ScheduledFuture worldResultFuture, pingFuture, currPingFuture; private WorldResult worldResult; + private int currentWorld; private Instant lastFetch; private boolean firstRun; @@ -158,6 +167,11 @@ public class WorldHopperPlugin extends Plugin private boolean ping; private boolean showWorldHopMessage; private SubscriptionFilterMode subscriptionFilter; + @Getter(AccessLevel.PACKAGE) + private boolean displayPing; + + @Getter(AccessLevel.PACKAGE) + private int currentPing; private final HotkeyListener previousKeyListener = new HotkeyListener(() -> this.previousKey) { @@ -189,6 +203,7 @@ public class WorldHopperPlugin extends Plugin addSubscriptions(); firstRun = true; + currentPing = -1; keyManager.registerKeyListener(previousKeyListener); keyManager.registerKeyListener(nextKeyListener); @@ -213,11 +228,18 @@ public class WorldHopperPlugin extends Plugin clientToolbar.addNavigation(navButton); } - panel.setFilterMode(this.subscriptionFilter); + overlayManager.add(worldHopperOverlay); + + panel.setFilterMode(config.subscriptionFilter()); + + // The plugin has its own executor for pings, as it blocks for a long time + hopperExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()); + // On first run this schedules an initial ping on hopperExecutorService worldResultFuture = executorService.scheduleAtFixedRate(this::tick, 0, WORLD_FETCH_TIMER, TimeUnit.MINUTES); - hopperExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()); - pingFuture = hopperExecutorService.scheduleAtFixedRate(this::pingWorlds, WORLD_PING_TIMER, WORLD_PING_TIMER, TimeUnit.MINUTES); + // Give some initial delay - this won't run until after pingInitialWorlds finishes from tick() anyway + pingFuture = hopperExecutorService.scheduleWithFixedDelay(this::pingNextWorld, 15, 3, TimeUnit.SECONDS); + currPingFuture = hopperExecutorService.scheduleWithFixedDelay(this::pingCurrentWorld, 15, 1, TimeUnit.SECONDS); } @Override @@ -228,6 +250,11 @@ public class WorldHopperPlugin extends Plugin pingFuture.cancel(true); pingFuture = null; + currPingFuture.cancel(true); + currPingFuture = null; + + overlayManager.remove(worldHopperOverlay); + keyManager.unregisterKeyListener(previousKeyListener); keyManager.unregisterKeyListener(nextKeyListener); @@ -482,7 +509,8 @@ public class WorldHopperPlugin extends Plugin if (firstRun) { firstRun = false; - hopperExecutorService.execute(this::pingWorlds); + // On first run we ping all of the worlds at once to initialize the ping values + hopperExecutorService.execute(this::pingInitialWorlds); } } @@ -504,6 +532,7 @@ public class WorldHopperPlugin extends Plugin new WorldClient().lookupWorlds() .subscribeOn(Schedulers.io()) + .take(1) .subscribe( (worldResult) -> { @@ -775,7 +804,10 @@ public class WorldHopperPlugin extends Plugin return null; } - private void pingWorlds() + /** + * Ping all worlds. This takes a long time and is only run on first run. + */ + private void pingInitialWorlds() { if (worldResult == null || !this.showSidebar || !this.ping) { @@ -804,5 +836,66 @@ public class WorldHopperPlugin extends Plugin this.ping = config.ping(); this.showWorldHopMessage = config.showWorldHopMessage(); this.subscriptionFilter = config.subscriptionFilter(); + this.displayPing = config.displayPing(); + } + + /** + * Ping the next world + */ + private void pingNextWorld() + { + if (worldResult == null || !config.showSidebar() || !config.ping()) + { + return; + } + + List worlds = worldResult.getWorlds(); + if (worlds.isEmpty()) + { + return; + } + + if (currentWorld >= worlds.size()) + { + // Wrap back around + currentWorld = 0; + } + + World world = worlds.get(currentWorld++); + + // If we are displaying the ping overlay, there is a separate scheduled task for the current world + boolean displayPing = config.displayPing() && client.getGameState() == GameState.LOGGED_IN; + if (displayPing && client.getWorld() == world.getId()) + { + return; + } + + int ping = Ping.ping(world); + log.trace("Ping for world {} is: {}", world.getId(), ping); + SwingUtilities.invokeLater(() -> panel.updatePing(world.getId(), ping)); + } + + /** + * Ping the current world for the ping overlay + */ + private void pingCurrentWorld() + { + // There is no reason to ping the current world if not logged in, as the overlay doesn't draw + if (worldResult == null || !config.displayPing() || client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + final World currentWorld = worldResult.findWorld(client.getWorld()); + if (currentWorld == null) + { + log.debug("unable to find current world: {}", client.getWorld()); + return; + } + + currentPing = Ping.ping(currentWorld); + log.trace("Ping for current world is: {}", currentPing); + + SwingUtilities.invokeLater(() -> panel.updatePing(currentWorld.getId(), currentPing)); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java index d15ddf86b1..1f47124afa 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/QuestStartLocation.java @@ -72,7 +72,7 @@ enum QuestStartLocation DARKNESS_OF_HALLOWVALE(Quest.DARKNESS_OF_HALLOWVALE, new WorldPoint(3494, 9628, 0)), DEATH_PLATEAU_TROLL_STRONGHOLD(new Quest[]{Quest.DEATH_PLATEAU, Quest.TROLL_STRONGHOLD}, new WorldPoint(2895, 3528, 0)), DEATH_TO_THE_DORGESHUUN(Quest.DEATH_TO_THE_DORGESHUUN, new WorldPoint(3316, 9613, 0)), - THE_DEPTHS_OF_DESPAIR(Quest.THE_DEPTHS_OF_DESPAIR, new WorldPoint(1846, 3556, 0)), + THE_DEPTHS_OF_DESPAIR(Quest.THE_DEPTHS_OF_DESPAIR, new WorldPoint(1780, 3569, 0)), DESERT_TREASURE(Quest.DESERT_TREASURE, new WorldPoint(3177, 3043, 0)), DEVIOUS_MINDS(Quest.DEVIOUS_MINDS, new WorldPoint(3405, 3492, 0)), THE_DIG_SITE(Quest.THE_DIG_SITE, new WorldPoint(3363, 3337, 0)), diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_agility.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_agility.json index 19fca53730..b72b8d59e9 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_agility.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_agility.json @@ -78,6 +78,12 @@ "name": "Pollnivneach Rooftop", "xp": 890 }, + { + "level": 75, + "icon": 23962, + "name": "Prifddinas Agility Course", + "xp": 1220 + }, { "level": 80, "icon": 11849, diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_farming.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_farming.json index bc5cde0ef6..5953579264 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_farming.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_farming.json @@ -240,6 +240,12 @@ "name": "Lantadyme", "xp": 134.5 }, + { + "level": 74, + "icon": 23962, + "name": "Crystal Tree", + "xp": 13366 + }, { "level": 75, "icon": 1513, diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java index 9d2ffa67e7..31c9bfd205 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java @@ -266,4 +266,94 @@ public class ChatCommandsPluginTest verify(configManager).setConfiguration(eq("personalbest.adam"), eq("prifddinas agility course"), eq(61)); verify(configManager).setConfiguration(eq("killcount.adam"), eq("prifddinas agility course"), eq(2)); } -} \ No newline at end of file + + @Test + public void testZukNewPb() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your TzKal-Zuk kill count is: 2.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: 104:31 (new personal best)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("tzkal-zuk"), eq(104 * 60 + 31)); + verify(configManager).setConfiguration(eq("killcount.adam"), eq("tzkal-zuk"), eq(2)); + } + + @Test + public void testZukKill() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your TzKal-Zuk kill count is: 3.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: 172:18. Personal best: 134:52", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("tzkal-zuk"), eq(134 * 60 + 52)); + verify(configManager).setConfiguration(eq("killcount.adam"), eq("tzkal-zuk"), eq(3)); + } + + @Test + public void testGgNewPb() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Fight duration: 1:36 (new personal best)", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: 179.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("grotesque guardians"), eq(96)); + verify(configManager).setConfiguration(eq("killcount.adam"), eq("grotesque guardians"), eq(179)); + } + + @Test + public void testGgKill() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Fight duration: 2:41. Personal best: 2:14", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: 32.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("grotesque guardians"), eq(2 * 60 + 14)); + verify(configManager).setConfiguration(eq("killcount.adam"), eq("grotesque guardians"), eq(32)); + } + + @Test + public void testGuantletPersonalBest() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: 10:24. Personal best: 7:59.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: 124.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("killcount.adam"), eq("gauntlet"), eq(124)); + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("gauntlet"), eq(7 * 60 + 59)); + } + + @Test + public void testGuantletNewPersonalBest() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: 10:24 (new personal best).", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: 124.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("gauntlet"), eq(10 * 60 + 24)); + verify(configManager).setConfiguration(eq("killcount.adam"), eq("gauntlet"), eq(124)); + } +}