Repository: runelite/runelite
Pull request #17547 (2024-03-02 07:41:42)

Item Identification: add sacred and olive oils
Added Sacred oil and Olive oil to Item ID, both of these items are slightly different shades of green and use the potion sprite (example image without IDs)

![image](https://github.com/runelite/runelite/assets/28745698/0603a4d3-bf2a-424b-926e-60451870bf0d)



Patch:
diff --git a/cache/pom.xml b/cache/pom.xml
index 9e7f4ac43..fa3179694 100644
--- a/cache/pom.xml
+++ b/cache/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.24-SNAPSHOT</version>
+		<version>1.10.25-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>cache</artifactId>
diff --git a/pom.xml b/pom.xml
index 3891210de..08732fc53 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
 	<groupId>net.runelite</groupId>
 	<artifactId>runelite-parent</artifactId>
-	<version>1.10.24-SNAPSHOT</version>
+	<version>1.10.25-SNAPSHOT</version>
 	<packaging>pom</packaging>
 
 	<name>RuneLite</name>
diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml
index 4d42a2956..18e0a22ee 100644
--- a/runelite-api/pom.xml
+++ b/runelite-api/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.24-SNAPSHOT</version>
+		<version>1.10.25-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>runelite-api</artifactId>
diff --git a/runelite-api/src/main/java/net/runelite/api/Hitsplat.java b/runelite-api/src/main/java/net/runelite/api/Hitsplat.java
index 4a172f41f..031c76b8e 100644
--- a/runelite-api/src/main/java/net/runelite/api/Hitsplat.java
+++ b/runelite-api/src/main/java/net/runelite/api/Hitsplat.java
@@ -32,16 +32,19 @@ import static net.runelite.api.HitsplatID.DAMAGE_MAX_ME_CYAN;
 import static net.runelite.api.HitsplatID.DAMAGE_MAX_ME_ORANGE;
 import static net.runelite.api.HitsplatID.DAMAGE_MAX_ME_WHITE;
 import static net.runelite.api.HitsplatID.DAMAGE_MAX_ME_YELLOW;
+import static net.runelite.api.HitsplatID.DAMAGE_MAX_ME_POISE;
 import static net.runelite.api.HitsplatID.DAMAGE_ME;
 import static net.runelite.api.HitsplatID.DAMAGE_ME_CYAN;
 import static net.runelite.api.HitsplatID.DAMAGE_ME_ORANGE;
 import static net.runelite.api.HitsplatID.DAMAGE_ME_WHITE;
 import static net.runelite.api.HitsplatID.DAMAGE_ME_YELLOW;
+import static net.runelite.api.HitsplatID.DAMAGE_ME_POISE;
 import static net.runelite.api.HitsplatID.DAMAGE_OTHER;
 import static net.runelite.api.HitsplatID.DAMAGE_OTHER_CYAN;
 import static net.runelite.api.HitsplatID.DAMAGE_OTHER_ORANGE;
 import static net.runelite.api.HitsplatID.DAMAGE_OTHER_WHITE;
 import static net.runelite.api.HitsplatID.DAMAGE_OTHER_YELLOW;
+import static net.runelite.api.HitsplatID.DAMAGE_OTHER_POISE;
 import net.runelite.api.annotations.HitsplatType;
 
 /**
@@ -85,11 +88,13 @@ public class Hitsplat
 			case DAMAGE_ME_YELLOW:
 			case DAMAGE_ME_ORANGE:
 			case DAMAGE_ME_WHITE:
+			case DAMAGE_ME_POISE:
 			case DAMAGE_MAX_ME:
 			case DAMAGE_MAX_ME_CYAN:
 			case DAMAGE_MAX_ME_ORANGE:
 			case DAMAGE_MAX_ME_YELLOW:
 			case DAMAGE_MAX_ME_WHITE:
+			case DAMAGE_MAX_ME_POISE:
 				return true;
 			default:
 				return false;
@@ -106,6 +111,7 @@ public class Hitsplat
 			case DAMAGE_OTHER_YELLOW:
 			case DAMAGE_OTHER_ORANGE:
 			case DAMAGE_OTHER_WHITE:
+			case DAMAGE_OTHER_POISE:
 				return true;
 			default:
 				return false;
diff --git a/runelite-api/src/main/java/net/runelite/api/HitsplatID.java b/runelite-api/src/main/java/net/runelite/api/HitsplatID.java
index 7c080bc81..29840fddb 100644
--- a/runelite-api/src/main/java/net/runelite/api/HitsplatID.java
+++ b/runelite-api/src/main/java/net/runelite/api/HitsplatID.java
@@ -30,10 +30,12 @@ public final class HitsplatID
 	public static final int BLOCK_OTHER = 13;
 	public static final int DAMAGE_ME = 16;
 	public static final int DAMAGE_OTHER = 17;
-	public static final int POISON = 2;
+	public static final int POISON = 65;
 	public static final int DISEASE = 4;
 	public static final int VENOM = 5;
 	public static final int HEAL = 6;
+	public static final int CYAN_UP = 11;
+	public static final int CYAN_DOWN = 15;
 	public static final int DAMAGE_ME_CYAN = 18;
 	public static final int DAMAGE_OTHER_CYAN = 19;
 	public static final int DAMAGE_ME_ORANGE = 20;
@@ -47,4 +49,12 @@ public final class HitsplatID
 	public static final int DAMAGE_MAX_ME_ORANGE = 45;
 	public static final int DAMAGE_MAX_ME_YELLOW = 46;
 	public static final int DAMAGE_MAX_ME_WHITE = 47;
+	public static final int DAMAGE_ME_POISE = 53;
+	public static final int DAMAGE_OTHER_POISE = 54;
+	public static final int DAMAGE_MAX_ME_POISE = 55;
+	public static final int CORRUPTION = 0;
+	public static final int PRAYER_DRAIN = 60;
+	public static final int BLEED = 67;
+	public static final int SANITY_DRAIN = 71;
+	public static final int SANITY_RESTORE = 72;
 }
\ No newline at end of file
diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml
index e07be7f10..90bbd02c2 100644
--- a/runelite-client/pom.xml
+++ b/runelite-client/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.24-SNAPSHOT</version>
+		<version>1.10.25-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>client</artifactId>
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 f96150cad..4343e4370 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
@@ -2469,11 +2469,33 @@ public class ChatCommandsPlugin extends Plugin
 
 			// Desert Treasure 2 bosses
 			case "the leviathan":
+			case "levi":
 				return "Leviathan";
 			case "duke":
 				return "Duke Sucellus";
 			case "the whisperer":
+			case "whisp":
+			case "wisp":
 				return "Whisperer";
+			case "vard":
+				return "Vardorvis";
+
+			// dt2 awakened variants
+			case "leviathan awakened":
+			case "the leviathan awakened":
+			case "levi awakened":
+				return "Leviathan (awakened)";
+			case "duke sucellus awakened":
+			case "duke awakened":
+				return "Duke Sucellus (awakened)";
+			case "whisperer awakened":
+			case "the whisperer awakened":
+			case "whisp awakened":
+			case "wisp awakened":
+				return "Whisperer (awakened)";
+			case "vardorvis awakened":
+			case "vard awakened":
+				return "Vardorvis (awakened)";
 
 			default:
 				return WordUtils.capitalize(boss);
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 634f8ca2a..4fa870b68 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
@@ -208,7 +208,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam
 		new SkillChallengeClue("Craft multiple cosmic runes from a single essence.", any("Pure essence or Daeyalt essence", item(ItemID.PURE_ESSENCE), item(ItemID.DAEYALT_ESSENCE))),
 		new SkillChallengeClue("Plant a watermelon seed.", item(ItemID.RAKE), item(ItemID.SEED_DIBBER), xOfItem(ItemID.WATERMELON_SEED, 3)),
 		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))),
+		new SkillChallengeClue("Smith a tier 2 or above Shayzien platebody.", "smith a tier 2 or above shayzien platebody.", ANY_HAMMER, xOfItem(ItemID.LOVAKITE_BAR, 4)),
 		// 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), item(ItemID.ABYSSAL_WHIP_OR), item(ItemID.ABYSSAL_TENTACLE), item(ItemID.ABYSSAL_TENTACLE_OR))),
 		new SkillChallengeClue("Smith a runite med helm.", ANY_HAMMER, item(ItemID.RUNITE_BAR)),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java
index f751cf05a..d9d36b693 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordConfig.java
@@ -57,7 +57,7 @@ public interface DiscordConfig extends Config
 	)
 	default ElapsedTimeType elapsedTimeType()
 	{
-		return ElapsedTimeType.ACTIVITY;
+		return ElapsedTimeType.TOTAL;
 	}
 
 	@ConfigItem(
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 32ec9bc2f..10184a56f 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
@@ -38,8 +38,8 @@ import net.runelite.api.Skill;
 enum DiscordGameEventType
 {
 
-	IN_MENU("In Menu", -3, true, true, true, false, true),
-	IN_GAME("In Game", -3, true, false, false, false, true),
+	IN_MENU("In Menu", -3, true, true, true, false),
+	IN_GAME("In Game", -3, true, false, false, false),
 	PLAYING_DEADMAN("Playing Deadman Mode", -3),
 	PLAYING_PVP("Playing in a PVP world", -3),
 	TRAINING_ATTACK(Skill.ATTACK),
@@ -494,11 +494,6 @@ enum DiscordGameEventType
 
 	private int priority;
 
-	/**
-	 * Marks this event as root event. (eg. event that should be used for total time tracking)
-	 */
-	private boolean root;
-
 	/**
 	 * Determines if event should clear other clearable events when triggered
 	 */
@@ -547,7 +542,7 @@ enum DiscordGameEventType
 		this.shouldClear = true;
 	}
 
-	DiscordGameEventType(String state, int priority, boolean shouldClear, boolean shouldTimeout, boolean shouldRestart, boolean shouldBeCleared, boolean root)
+	DiscordGameEventType(String state, int priority, boolean shouldClear, boolean shouldTimeout, boolean shouldRestart, boolean shouldBeCleared)
 	{
 		this.state = state;
 		this.priority = priority;
@@ -555,12 +550,11 @@ enum DiscordGameEventType
 		this.shouldTimeout = shouldTimeout;
 		this.shouldRestart = shouldRestart;
 		this.shouldBeCleared = shouldBeCleared;
-		this.root = root;
 	}
 
 	DiscordGameEventType(String state, int priority)
 	{
-		this(state, priority, true, false, false, true, false);
+		this(state, priority, true, false, false, true);
 	}
 
 	private static String training(final Skill skill)
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java
index 9e7677ddd..e4a2a1747 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/discord/DiscordState.java
@@ -36,12 +36,14 @@ import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.inject.Named;
 import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
 import net.runelite.client.discord.DiscordPresence;
 import net.runelite.client.discord.DiscordService;
 
 /**
  * This class contains data about currently active discord state.
  */
+@Slf4j
 class DiscordState
 {
 	@Data
@@ -124,6 +126,8 @@ class DiscordState
 			.compare(b.getUpdated(), a.getUpdated())
 			.result());
 
+		log.debug("Events: {}", events);
+
 		updatePresenceWithLatestEvent();
 	}
 
@@ -186,15 +190,12 @@ class DiscordState
 				startTime = null;
 				break;
 			case TOTAL:
-				// We are tracking total time spent instead of per activity time so try to find
-				// root event as this indicates start of tracking and find last updated one
-				// to determine correct state we are in
+				// Use the start time of the IN_GAME event, which will always be
+				// the lowest.
 				startTime = events.stream()
-					.filter(e -> e.getType().isRoot())
-					.sorted((a, b) -> b.getUpdated().compareTo(a.getUpdated()))
 					.map(EventWithTime::getStart)
-					.findFirst()
-					.orElse(event.getStart());
+					.min(Instant::compareTo)
+					.get();
 				break;
 			case ACTIVITY:
 			default:
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 605e39a78..8de975350 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
@@ -317,6 +317,8 @@ enum ItemIdentification
 
 	SERUM_207(Type.POTION, "Ser207", "S7", ItemID.SERUM_207_4, ItemID.SERUM_207_3, ItemID.SERUM_207_2, ItemID.SERUM_207_1),
 	SERUM_208(Type.POTION, "Ser208", "S8", ItemID.SERUM_208_4, ItemID.SERUM_208_3, ItemID.SERUM_208_2, ItemID.SERUM_208_1),
+	SACRED_OIL(Type.POTION, "SaOil", "SO", ItemID.SACRED_OIL4, ItemID.SACRED_OIL3, ItemID.SACRED_OIL2, ItemID.SACRED_OIL1),
+	OLIVE_OIL(Type.POTION, "Olive", "Oli", ItemID.OLIVE_OIL4, ItemID.OLIVE_OIL3, ItemID.OLIVE_OIL2, ItemID.OLIVE_OIL1),
 	COMPOST_POTION(Type.POTION, "Compost", "COM", ItemID.COMPOST_POTION4, ItemID.COMPOST_POTION3, ItemID.COMPOST_POTION2, ItemID.COMPOST_POTION1),
 
 	AGILITY(Type.POTION, "Agility", "Ag", ItemID.AGILITY_POTION4, ItemID.AGILITY_POTION3, ItemID.AGILITY_POTION2, ItemID.AGILITY_POTION1),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java
index 6a55d46b5..f51eb6ddf 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/mining/MiningPlugin.java
@@ -93,7 +93,7 @@ public class MiningPlugin extends Plugin
 			"(?:manage to|just)" +
 			" (?:mined?|quarry) " +
 			"(?:some|an?) " +
-			"(?:copper|tin|clay|iron|silver|coal|gold|mithril|adamantite|runeite|amethyst|sandstone|granite|barronite shards|barronite deposit|Opal|piece of Jade|Red Topaz|Emerald|Sapphire|Ruby|Diamond)" +
+			"(?:copper|tin|clay|iron|silver|coal|gold|mithril|adamantite|runite|amethyst|sandstone|granite|barronite shards|barronite deposit|Opal|piece of Jade|Red Topaz|Emerald|Sapphire|Ruby|Diamond)" +
 			"(?:\\.|!)");
 
 	@Inject
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java
index d1805e232..49e52b0b1 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/npcunaggroarea/NpcAggroAreaPlugin.java
@@ -285,7 +285,7 @@ public class NpcAggroAreaPlugin extends Plugin
 
 		for (String pattern : npcNamePatterns)
 		{
-			if (npc.getCombatLevel() != 0 && WildcardMatcher.matches(pattern, npcName))
+			if (WildcardMatcher.matches(pattern, npcName))
 			{
 				return true;
 			}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java
index afac7d7b6..02e9c5a47 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java
@@ -57,7 +57,6 @@ enum GameTimer
 	IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued/Saturated heart", false),
 	VENGEANCE(SpriteID.SPELL_VENGEANCE, GameTimerImageType.SPRITE, "Vengeance", 30, ChronoUnit.SECONDS),
 	HEAL_GROUP(SpriteID.SPELL_HEAL_GROUP, GameTimerImageType.SPRITE, "Heal Group", 150, GAME_TICKS),
-	EXSUPERANTIFIRE(ItemID.EXTENDED_SUPER_ANTIFIRE4, GameTimerImageType.ITEM, "Extended Super AntiFire", 6, ChronoUnit.MINUTES),
 	OVERLOAD_RAID(ItemID.OVERLOAD_4_20996, GameTimerImageType.ITEM, "Overload", false),
 	PRAYER_ENHANCE(ItemID.PRAYER_ENHANCE_4, GameTimerImageType.ITEM, "Prayer enhance", 290, ChronoUnit.SECONDS, true),
 	GOD_WARS_ALTAR(SpriteID.SKILL_PRAYER, GameTimerImageType.SPRITE, "God wars altar", false),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java
index 4394f1487..8c42216dd 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java
@@ -26,6 +26,7 @@
  */
 package net.runelite.client.plugins.timers;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Provides;
 import java.time.Duration;
@@ -634,6 +635,7 @@ public class TimersPlugin extends Plugin
 		if (!config.showCannon())
 		{
 			removeGameTimer(CANNON);
+			removeGameTimer(CANNON_REPAIR);
 		}
 
 		if (!config.showMagicImbue())
@@ -755,6 +757,21 @@ public class TimersPlugin extends Plugin
 		{
 			removeGameTimer(BLESSED_CRYSTAL_SCARAB);
 		}
+
+		if (!config.showAbyssalSireStun())
+		{
+			removeGameTimer(ABYSSAL_SIRE_STUN);
+		}
+
+		if (!config.showPickpocketStun())
+		{
+			removeGameTimer(PICKPOCKET_STUN);
+		}
+
+		if (!config.showSpellbookSwap())
+		{
+			removeGameTimer(SPELLBOOK_SWAP);
+		}
 	}
 
 	@Subscribe
@@ -1198,7 +1215,8 @@ public class TimersPlugin extends Plugin
 		return t;
 	}
 
-	private void removeGameTimer(GameTimer timer)
+	@VisibleForTesting
+	void removeGameTimer(GameTimer timer)
 	{
 		infoBoxManager.removeIf(t -> t instanceof TimerTimer && ((TimerTimer) t).getTimer() == timer);
 	}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/KourendTaskLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/KourendTaskLocation.java
deleted file mode 100644
index 40b86e7ab..000000000
--- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/KourendTaskLocation.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2020, Brooklyn <https://github.com/Broooklyn>
- * 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 HOLDER 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.worldmap;
-
-import lombok.Getter;
-import net.runelite.api.coords.WorldPoint;
-
-@Getter
-enum KourendTaskLocation
-{
-	ARCEUUS_LIBRARY_SOUTH("Arceuus Task (0%) - Library Assistance", new WorldPoint(1622, 3801, 0)),
-	ARCEUUS_LIBRARY_NORTH("Arceuus Task (0%) - Library Assistance", new WorldPoint(1638, 3817, 0)),
-	ARCEUUS_DENSE_ESSENCE("Arceuus Task (25%) - Dense Essence Mining", new WorldPoint(1757, 3852, 0)),
-	ARCEUUS_REANIMATE_CREATURES("Arceuus Task (60%) - Creature Reanimation", new WorldPoint(1714, 3883, 0)),
-	ARCEUUS_BLOOD_ALTAR("Arceuus Unlock (100%) - Blood Rune Crafting", new WorldPoint(1716, 3829, 0)),
-	ARCEUUS_SOUL_ALTAR("Arceuus Unlock (100%) - Soul Rune Crafting", new WorldPoint(1814, 3854, 0)),
-
-	HOSIDIUS_PLOUGH_NORTH("Hosidius Task (0%) - Ploughs", new WorldPoint(1770, 3550, 0)),
-	HOSIDIUS_PLOUGH_SOUTH("Hosidius Task (0%) - Ploughs", new WorldPoint(1769, 3528, 0)),
-	HOSIDUIS_FERTILISER("Hosidius Task (5%) - Making Fertilizer", new WorldPoint(1701, 3527, 0)),
-	HOSIDIUS_SPIRIT_TREE("Hosidius Unlock (35%) - Spirit Tree Patch", new WorldPoint(1695, 3545, 0)),
-	HOSIDIUS_MESS("Hosidius Task (45%) - Mess", new WorldPoint(1639, 3629, 0)),
-	HOSIDIUS_FARMING_PATCH("Hosidius Unlock (50%) - Disease Protection", new WorldPoint(1740, 3552, 0)),
-	HOSIDIUS_VINERY("Hosidius Task (65%) - Grape Planting", new WorldPoint(1804, 3564, 0)),
-	HOSIDIUS_TITHE_FARM("Hosidius Unlock (100%) - Tithe Farm", new WorldPoint(1802, 3499, 0)),
-	HOSIDIUS_KITCHEN("Hosidius Unlock (100%) - Kitchen", new WorldPoint(1678, 3618, 0)),
-
-	LOVAKENGJ_DYNAMITE("Lovakengj Task (0%) - Making Juniper Charcoal", new WorldPoint(1718, 3472, 0)),
-	LOVAKENGJ_SULFUR("Lovakengj Task (0%) - Mining Volcanic Sulphur", new WorldPoint(1437, 3861, 0)),
-	LOVAKENGJ_ARMOURER_T1("Lovakengj Task (30%) - Armourer (Tier 1)", new WorldPoint(1453, 3750, 0)),
-	LOVAKENGJ_ARMOURER_T2("Lovakengj Task (40%) - Armourer (Tier 2)", new WorldPoint(1436, 3784, 0)),
-	LOVAKENGJ_ARMOURER_T3("Lovakengj Task (50%) - Armourer (Tier 3)", new WorldPoint(1430, 3797, 0)),
-	LOVAKENGJ_ARMOURER_T4("Lovakengj Task (60%) - Armourer (Tier 4)", new WorldPoint(1460, 3763, 0)),
-	LOVAKENGJ_ARMOURER_T5("Lovakengj Task (70%) - Armourer (Tier 5)", new WorldPoint(1524, 3755, 0)),
-	LOVAKENGJ_BLAST_MINE("Lovakengj Unlock (100%) - Blast Mine", new WorldPoint(1488, 3865, 0)),
-
-	PISCARILIUS_CRANE_REPAIR("Piscarilius Task (0%) - Fishing Crane Repair", new WorldPoint(1820, 3742, 0)),
-	PISCARILIUS_FRESH_FISH("Piscarilius Task (15%) - Fish Delivery", new WorldPoint(1831, 3716, 0)),
-	PISCARILIUS_SANDWORMS("Piscarilius Task (30%) - Hunting Sandworms", new WorldPoint(1841, 3789, 0)),
-	PISCARILIUS_STEALING_ARTEFACTS("Piscarilius Task (75%) - Stealing Artefacts", new WorldPoint(1849, 3753, 0)),
-
-	SHAYZIEN_HEALING_SOLDIERS("Shayzien Task (0%) - Healing Wounded Soldiers", new WorldPoint(1528, 3627, 0)),
-	SHAYZIEN_LIZARDMEN_EAST("Shayzien Task (5%) - Killing Lizardmen", new WorldPoint(1570, 3668, 0)),
-	SHAYZIEN_LIZARDMEN_WEST("Shayzien Task (5%) - Killing Lizardmen", new WorldPoint(1471, 3686, 0)),
-	SHAYZIEN_ORGANIZED_CRIME("Shayzien Task (40%) - Organized Crime", new WorldPoint(1504, 3635, 0)),
-	SHAYZIEN_COMBAT_RING("Shayzien Task (60%) - Combat Ring", new WorldPoint(1541, 3628, 0)),
-	SHAYZIEN_LIZARDMAN_SHAMANS("Shayzien Unlock (100%) - Lizardman Shamans", new WorldPoint(1455, 3693, 0));
-
-	private final String tooltip;
-	private final WorldPoint location;
-
-	KourendTaskLocation(String tooltip, WorldPoint location)
-	{
-		this.tooltip = tooltip;
-		this.location = location;
-	}
-}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java
index fcd4c9f0e..6543c603c 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapConfig.java
@@ -295,15 +295,4 @@ public interface WorldMapConfig extends Config
 	{
 		return true;
 	}
-
-	@ConfigItem(
-		keyName = WorldMapPlugin.CONFIG_KEY_KOUREND_TASK_TOOLTIPS,
-		name = "Kourend task tooltips",
-		description = "Indicates the task or unlock for Kourend Favour locations",
-		position = 25
-	)
-	default boolean kourendTaskTooltips()
-	{
-		return true;
-	}
 }
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java
index 1fd034198..5ea6261f7 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/WorldMapPlugin.java
@@ -104,7 +104,6 @@ public class WorldMapPlugin extends Plugin
 	static final String CONFIG_KEY_DUNGEON_TOOLTIPS = "dungeonTooltips";
 	static final String CONFIG_KEY_HUNTER_AREA_TOOLTIPS = "hunterAreaTooltips";
 	static final String CONFIG_KEY_FISHING_SPOT_TOOLTIPS = "fishingSpotTooltips";
-	static final String CONFIG_KEY_KOUREND_TASK_TOOLTIPS = "kourendTaskTooltips";
 
 	static
 	{
@@ -538,21 +537,6 @@ public class WorldMapPlugin extends Plugin
 					.forEach(worldMapPointManager::add)
 			);
 		}
-
-		worldMapPointManager.removeIf(isType(MapPoint.Type.KOUREND_TASK));
-		if (config.kourendTaskTooltips())
-		{
-			Arrays.stream(KourendTaskLocation.values())
-				.map(l ->
-					MapPoint.builder()
-						.type(MapPoint.Type.KOUREND_TASK)
-						.worldPoint(l.getLocation())
-						.image(BLANK_ICON)
-						.tooltip(l.getTooltip())
-						.build()
-				)
-				.forEach(worldMapPointManager::add);
-		}
 	}
 
 	private void updateQuestStartPointIcons()
diff --git a/runelite-client/src/main/scripts/ChatDefaultOnKey.hash b/runelite-client/src/main/scripts/ChatDefaultOnKey.hash
index 6111270f5..b9a7ec823 100644
--- a/runelite-client/src/main/scripts/ChatDefaultOnKey.hash
+++ b/runelite-client/src/main/scripts/ChatDefaultOnKey.hash
@@ -1,1 +1,1 @@
-4935AB305430A9D41C42D00C1E1EF6853ABC54822BC21DC3CADCD3DD3485F446
\ No newline at end of file
+C453D366A50A1133860CFDC3983FF0A7FC6211B4A009B2DB1E10235A0109B6AF
\ No newline at end of file
diff --git a/runelite-client/src/main/scripts/ChatDefaultOnKey.rs2asm b/runelite-client/src/main/scripts/ChatDefaultOnKey.rs2asm
index d230b16c4..5c871cb34 100644
--- a/runelite-client/src/main/scripts/ChatDefaultOnKey.rs2asm
+++ b/runelite-client/src/main/scripts/ChatDefaultOnKey.rs2asm
@@ -1027,7 +1027,7 @@ LABEL828:
    if_icmpeq              LABEL832
    jump                   LABEL877
 LABEL832:
-   iconst                 40697936
+   iconst                 40697938
    iconst                 1
    cc_find               
    iconst                 1
diff --git a/runelite-jshell/pom.xml b/runelite-jshell/pom.xml
index f3eb2c9db..1a526d30f 100644
--- a/runelite-jshell/pom.xml
+++ b/runelite-jshell/pom.xml
@@ -30,7 +30,7 @@
     <parent>
         <groupId>net.runelite</groupId>
         <artifactId>runelite-parent</artifactId>
-        <version>1.10.24-SNAPSHOT</version>
+        <version>1.10.25-SNAPSHOT</version>
     </parent>
 
     <artifactId>jshell</artifactId>
diff --git a/runelite-maven-plugin/pom.xml b/runelite-maven-plugin/pom.xml
index fd5c5e7e6..b2306ce84 100644
--- a/runelite-maven-plugin/pom.xml
+++ b/runelite-maven-plugin/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.24-SNAPSHOT</version>
+		<version>1.10.25-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>runelite-maven-plugin</artifactId>


Test patch:
diff --git a/cache/src/test/java/net/runelite/cache/StoreLocation.java b/cache/src/test/java/net/runelite/cache/StoreLocation.java
index 890e43e5e..e03bff8c4 100644
--- a/cache/src/test/java/net/runelite/cache/StoreLocation.java
+++ b/cache/src/test/java/net/runelite/cache/StoreLocation.java
@@ -57,7 +57,7 @@ public class StoreLocation
 		}
 		catch (IOException ex)
 		{
-			logger.warn("unable to initialize cache tmp area", ex);
+			throw new RuntimeException(ex);
 		}
 	}
 
@@ -71,23 +71,31 @@ public class StoreLocation
 			return file;
 		}
 
-		file.mkdir();
+		try
+		{
+			file.mkdir();
 
-		// Copy over files
-		InputStream in = StoreLocation.class.getResourceAsStream("/main_file_cache.dat2");
-		Files.copy(in, new File(file, "main_file_cache.dat2").toPath());
+			// Copy over files
+			InputStream in = StoreLocation.class.getResourceAsStream("/main_file_cache.dat2");
+			Files.copy(in, new File(file, "main_file_cache.dat2").toPath());
 
-		in = StoreLocation.class.getResourceAsStream("/main_file_cache.idx255");
-		Files.copy(in, new File(file, "main_file_cache.idx255").toPath());
+			in = StoreLocation.class.getResourceAsStream("/main_file_cache.idx255");
+			Files.copy(in, new File(file, "main_file_cache.idx255").toPath());
 
-		for (int i = 0; i <= NUM_INDEXES; ++i)
+			for (int i = 0; i <= NUM_INDEXES; ++i)
+			{
+				in = StoreLocation.class.getResourceAsStream("/main_file_cache.idx" + i);
+				Files.copy(in, new File(file, "main_file_cache.idx" + i).toPath());
+			}
+
+			logger.info("Set up cache working directory to {}", file);
+		}
+		catch (Exception ex)
 		{
-			in = StoreLocation.class.getResourceAsStream("/main_file_cache.idx" + i);
-			Files.copy(in, new File(file, "main_file_cache.idx" + i).toPath());
+			file.delete();
+			throw ex;
 		}
 
-		logger.info("Set up cache working directory to {}", file);
-
 		return file;
 	}
 
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/mining/MiningPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/mining/MiningPluginTest.java
index 2d5616d61..a14cc3585 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/mining/MiningPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/mining/MiningPluginTest.java
@@ -83,6 +83,12 @@ public class MiningPluginTest
 		testMessage("You manage to mine some iron.");
 	}
 
+	@Test
+	public void testRunite()
+	{
+		testMessage("You manage to mine some runite.");
+	}
+
 	@Test
 	public void testSandstone()
 	{
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java
index ebb71d00a..0ae89c83c 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/timers/TimersPluginTest.java
@@ -38,6 +38,7 @@ import net.runelite.api.Skill;
 import net.runelite.api.Varbits;
 import net.runelite.api.events.ChatMessage;
 import net.runelite.api.events.VarbitChanged;
+import net.runelite.client.events.ConfigChanged;
 import net.runelite.client.game.ItemManager;
 import net.runelite.client.game.SpriteManager;
 import net.runelite.client.ui.overlay.infobox.InfoBox;
@@ -55,6 +56,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.nullable;
 import org.mockito.Mock;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -93,6 +95,21 @@ public class TimersPluginTest
 		Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
 	}
 
+	@Test
+	public void removeTimersOnConfigChanged()
+	{
+		timersPlugin = spy(timersPlugin);
+		final ConfigChanged configChanged = new ConfigChanged();
+		configChanged.setGroup(TimersConfig.GROUP);
+
+		timersPlugin.onConfigChanged(configChanged);
+
+		for (GameTimer timer : GameTimer.values())
+		{
+			verify(timersPlugin).removeGameTimer(timer);
+		}
+	}
+
 	@Test
 	public void testDivineRanging()
 	{