diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt
index 22bd5bf227..b693ce07ef 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.7.11.1"
+ const val rlVersion = "1.7.11.2"
const val openosrsVersion = "4.8.1"
diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java
index b9a9f6037e..0800d2f5f4 100644
--- a/runelite-api/src/main/java/net/runelite/api/Client.java
+++ b/runelite-api/src/main/java/net/runelite/api/Client.java
@@ -673,12 +673,19 @@ public interface Client extends GameEngine
boolean isMenuOpen();
/**
- * Gets the angle of the map, or camera yaw.
+ * Gets the angle of the map, or target camera yaw.
*
* @return the map angle
*/
int getMapAngle();
+ /**
+ * Set the target camera yaw
+ *
+ * @param cameraYawTarget
+ */
+ void setCameraYawTarget(int cameraYawTarget);
+
/**
* Checks whether the client window is currently resized.
*
diff --git a/runelite-client/src/main/java/net/runelite/client/config/ChatColorConfig.java b/runelite-client/src/main/java/net/runelite/client/config/ChatColorConfig.java
index 90fc5adbe0..da8eb41f12 100644
--- a/runelite-client/src/main/java/net/runelite/client/config/ChatColorConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/config/ChatColorConfig.java
@@ -185,7 +185,7 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 14,
- keyName = "opaqueClanChatMessageHighlight",
+ keyName = "opaqueClanMessageHighlight",
name = "Clan chat message highlight",
description = "Color of highlights in Clan Chat messages",
section = opaqueSection
@@ -582,7 +582,7 @@ public interface ChatColorConfig extends Config
@ConfigItem(
position = 64,
- keyName = "transparentClanChatMessageHighlight",
+ keyName = "transparentClanMessageHighlight",
name = "Clan chat message highlight (transparent)",
description = "Color of highlights in Clan Chat messages (transparent)",
section = transparentSection
diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
index a33e58d77e..be41c03807 100644
--- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
+++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java
@@ -448,7 +448,7 @@ public class ConfigManager
public void setConfiguration(String groupName, String profile, String key, @NonNull String value)
{
- if (Strings.isNullOrEmpty(groupName) || Strings.isNullOrEmpty(key))
+ if (Strings.isNullOrEmpty(groupName) || Strings.isNullOrEmpty(key) || key.indexOf(':') != -1)
{
throw new IllegalArgumentException();
}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java
index 5f019c82ca..250cb8f247 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java
@@ -191,4 +191,15 @@ public interface CameraConfig extends Config
{
return false;
}
+
+ @ConfigItem(
+ keyName = "preserveYaw",
+ name = "Preserve yaw on world hop",
+ description = "Preserves the camera yaw (left/right) when world hopping.",
+ position = 14
+ )
+ default boolean preserveYaw()
+ {
+ return false;
+ }
}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java
index f650d3efba..b2ac448629 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java
@@ -43,6 +43,7 @@ import net.runelite.api.VarPlayer;
import net.runelite.api.events.BeforeRender;
import net.runelite.api.events.ClientTick;
import net.runelite.api.events.FocusChanged;
+import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.ScriptPreFired;
@@ -89,7 +90,8 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener
* Whether or not the current menu has any non-ignored menu entries
*/
private boolean menuHasEntries;
-
+ private int savedCameraYaw;
+
@Inject
private Client client;
@@ -418,6 +420,24 @@ public class CameraPlugin extends Plugin implements KeyListener, MouseListener
}
}
+ @Subscribe
+ public void onGameStateChanged(GameStateChanged gameStateChanged)
+ {
+ switch (gameStateChanged.getGameState())
+ {
+ case HOPPING:
+ savedCameraYaw = client.getMapAngle();
+ break;
+ case LOGGED_IN:
+ if (savedCameraYaw != 0 && config.preserveYaw())
+ {
+ client.setCameraYawTarget(savedCameraYaw);
+ }
+ savedCameraYaw = 0;
+ break;
+ }
+ }
+
/**
* The event that is triggered when a mouse button is pressed
* In this method the right click is changed to a middle-click to enable rotating the camera
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 33f282d513..6a2cfc1323 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
@@ -98,7 +98,7 @@ public class ChatCommandsPlugin extends Plugin
private static final String COX_TEAM_SIZES = "(?:\\d+(?:\\+|-\\d+)? players|Solo)";
private static final Pattern RAIDS_PB_PATTERN = Pattern.compile("
Congratulations - your raid is complete!
Team size: " + COX_TEAM_SIZES + " Duration: (?[0-9:]+(?:\\.[0-9]+)?) \\(new personal best\\)");
private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("Congratulations - your raid is complete!
Team size: " + COX_TEAM_SIZES + " Duration: [0-9:.]+ Personal best: (?[0-9:]+(?:\\.[0-9]+)?)");
- private static final Pattern TOB_WAVE_PB_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: (?[0-9:]+(?:\\.[0-9]+)?) \\(Personal best!\\)");
+ private static final Pattern TOB_WAVE_PB_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: (?[0-9:]+(?:\\.[0-9]+)?) \\(new personal best\\)");
private static final Pattern TOB_WAVE_DURATION_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: [0-9:.]+
Personal best: (?[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in) [0-9:.]+\\. Personal best: (?:)?(?[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?i)^(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in) (?[0-9:]+(?:\\.[0-9]+)?) \\(new personal best\\)");
@@ -245,6 +245,11 @@ public class ChatCommandsPlugin extends Plugin
configManager.setRSProfileConfiguration("killcount", boss.toLowerCase(), killcount);
}
+ private void unsetKc(String boss)
+ {
+ configManager.unsetRSProfileConfiguration("killcount", boss.toLowerCase());
+ }
+
private int getKc(String boss)
{
Integer killCount = configManager.getRSProfileConfiguration("killcount", boss.toLowerCase(), int.class);
@@ -256,6 +261,11 @@ public class ChatCommandsPlugin extends Plugin
configManager.setRSProfileConfiguration("personalbest", boss.toLowerCase(), seconds);
}
+ private void unsetPb(String boss)
+ {
+ configManager.unsetRSProfileConfiguration("personalbest", boss.toLowerCase());
+ }
+
private double getPb(String boss)
{
Double personalBest = configManager.getRSProfileConfiguration("personalbest", boss.toLowerCase(), double.class);
@@ -280,19 +290,30 @@ public class ChatCommandsPlugin extends Plugin
String boss = matcher.group(1);
int kc = Integer.parseInt(matcher.group(2));
- boss = KILLCOUNT_RENAMES.getOrDefault(boss, boss);
+ String renamedBoss = KILLCOUNT_RENAMES
+ .getOrDefault(boss, boss)
+ // The config service doesn't support keys with colons in them
+ .replace(":", "");
+ if (boss != renamedBoss)
+ {
+ // Unset old TOB kc
+ unsetKc(boss);
+ unsetPb(boss);
+ unsetKc(boss.replace(":", "."));
+ unsetPb(boss.replace(":", "."));
+ }
- setKc(boss, kc);
+ setKc(renamedBoss, kc);
// 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);
+ log.debug("Got out-of-order personal best for {}: {}", renamedBoss, lastPb);
+ setPb(renamedBoss, lastPb);
lastPb = -1;
}
else
{
- lastBossKill = boss;
+ lastBossKill = renamedBoss;
lastBossTime = client.getTickCount();
}
return;
@@ -1687,6 +1708,19 @@ public class ChatCommandsPlugin extends Plugin
case "raids 2":
return "Theatre of Blood";
+ case "Theatre of Blood: Story Mode":
+ case "tob sm":
+ case "tob story mode":
+ case "tob story":
+ return "Theatre of Blood Story Mode";
+
+ case "Theatre of Blood: Hard Mode":
+ case "tob cm":
+ case "tob hm":
+ case "tob hard mode":
+ case "tob hard":
+ return "Theatre of Blood Hard Mode";
+
// agility course
case "prif":
case "prifddinas":
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java
index 3cde11fec9..5f9a99deee 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CrypticClue.java
@@ -330,6 +330,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
private final String text;
private final String npc;
private final int objectId;
+ @Nullable
private final WorldPoint location;
private final String solution;
@Nullable
@@ -371,7 +372,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
this(text, npc, objectId, location, solution, null);
}
- private CrypticClue(String text, String npc, int objectId, WorldPoint location, String solution, @Nullable String questionText)
+ private CrypticClue(String text, String npc, int objectId, @Nullable WorldPoint location, String solution, @Nullable String questionText)
{
this.text = text;
this.npc = npc;
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java
index 52c78d94c8..9672d4b351 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClue.java
@@ -30,6 +30,7 @@ import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.runelite.api.InventoryID;
@@ -167,6 +168,7 @@ public class ThreeStepCrypticClue extends ClueScroll implements TextClueScroll,
return clueSteps.stream()
.filter(s -> !s.getValue())
.map(s -> s.getKey().getLocation())
+ .filter(Objects::nonNull)
.toArray(WorldPoint[]::new);
}
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 2c54f1744b..93d0046a9f 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
@@ -199,7 +199,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private int vboUiHandle;
private int fboSceneHandle;
- private int texSceneHandle;
private int rboSceneHandle;
// scene vertex buffer
@@ -297,7 +296,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
{
try
{
- texSceneHandle = fboSceneHandle = rboSceneHandle = -1; // AA FBO
+ fboSceneHandle = rboSceneHandle = -1; // AA FBO
unorderedModels = smallModels = largeModels = 0;
drawingModel = false;
@@ -737,28 +736,13 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, aaSamples, gl.GL_RGBA, width, height);
gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, rboSceneHandle);
- // Create texture
- texSceneHandle = glGenTexture(gl);
- gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, texSceneHandle);
- gl.glTexImage2DMultisample(gl.GL_TEXTURE_2D_MULTISAMPLE, aaSamples, gl.GL_RGBA, width, height, true);
-
- // Bind texture
- gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D_MULTISAMPLE, texSceneHandle, 0);
-
// Reset
- gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, 0);
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0);
gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0);
}
private void shutdownAAFbo()
{
- if (texSceneHandle != -1)
- {
- glDeleteTexture(gl, texSceneHandle);
- texSceneHandle = -1;
- }
-
if (fboSceneHandle != -1)
{
glDeleteFrameBuffer(gl, fboSceneHandle);
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 f25c479d77..bfc455b405 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
@@ -110,6 +110,13 @@ public class IdleNotifierPlugin extends Plugin
return configManager.getConfig(IdleNotifierConfig.class);
}
+ @Override
+ protected void startUp() throws Exception
+ {
+ // can't tell when 6hr will be if enabled while already logged in
+ sixHourWarningTime = null;
+ }
+
@Subscribe
public void onAnimationChanged(AnimationChanged event)
{
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java
index 81d28d584e..a68231eeb5 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java
@@ -419,6 +419,17 @@ public interface MenuEntrySwapperConfig extends Config
return false;
}
+ @ConfigItem(
+ keyName = "swapTeleToPoh",
+ name = "Tele to POH",
+ description = "Swap Wear with Tele to POH on the construction cape",
+ section = itemSection
+ )
+ default boolean swapTeleToPoh()
+ {
+ return false;
+ }
+
@ConfigItem(
keyName = "swapAbyssTeleport",
name = "Teleport to Abyss",
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java
index 151ebbe5f4..6345148989 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java
@@ -348,6 +348,8 @@ public class MenuEntrySwapperPlugin extends Plugin
swap("value", "sell 10", () -> shiftModifier() && config.shopSell() == SellMode.SELL_10);
swap("value", "sell 50", () -> shiftModifier() && config.shopSell() == SellMode.SELL_50);
+ swap("wear", "tele to poh", config::swapTeleToPoh);
+
swap("wear", "rub", config::swapTeleportItem);
swap("wear", "teleport", config::swapTeleportItem);
swap("wield", "teleport", config::swapTeleportItem);
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/alchemy/AlchemyRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/alchemy/AlchemyRoom.java
index 5e8918ac07..485a7f6d91 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/alchemy/AlchemyRoom.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/alchemy/AlchemyRoom.java
@@ -96,6 +96,7 @@ public class AlchemyRoom extends MTARoom
private AlchemyItem best;
private Cupboard suggestion;
+ private boolean hintSet;
@Inject
private AlchemyRoom(Client client, MTAConfig config, MTAPlugin plugin, ItemManager itemManager, InfoBoxManager infoBoxManager)
@@ -221,6 +222,11 @@ public class AlchemyRoom extends MTARoom
if (!inside())
{
reset();
+ if (hintSet)
+ {
+ client.clearHintArrow();
+ hintSet = false;
+ }
}
}
}
@@ -381,6 +387,7 @@ public class AlchemyRoom extends MTARoom
{
client.setHintArrow(object.getWorldLocation());
found = true;
+ hintSet = true;
}
BufferedImage image = itemManager.getImage(alchemyItem.getId());
@@ -395,6 +402,7 @@ public class AlchemyRoom extends MTARoom
if (!found && suggestion != null)
{
client.setHintArrow(suggestion.gameObject.getWorldLocation());
+ hintSet = true;
}
}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/mta/enchantment/EnchantmentRoom.java b/runelite-client/src/main/java/net/runelite/client/plugins/mta/enchantment/EnchantmentRoom.java
index aeb029fb81..56e9f31057 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/mta/enchantment/EnchantmentRoom.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/mta/enchantment/EnchantmentRoom.java
@@ -50,6 +50,7 @@ public class EnchantmentRoom extends MTARoom
private final Client client;
private final List dragonstones = new ArrayList<>();
+ private boolean hintSet;
@Inject
private EnchantmentRoom(MTAConfig config, Client client)
@@ -64,6 +65,11 @@ public class EnchantmentRoom extends MTARoom
if (gameStateChanged.getGameState() == GameState.LOADING)
{
dragonstones.clear();
+ if (hintSet)
+ {
+ client.clearHintArrow();
+ hintSet = false;
+ }
}
}
@@ -79,10 +85,12 @@ public class EnchantmentRoom extends MTARoom
if (nearest != null)
{
client.setHintArrow(nearest);
+ hintSet = true;
}
else
{
client.clearHintArrow();
+ hintSet = false;
}
}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java
index 44d9d58b51..1dd5c53174 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotConfig.java
@@ -253,11 +253,23 @@ public interface ScreenshotConfig extends Config
return false;
}
+ @ConfigItem(
+ keyName = "collectionLogEntries",
+ name = "Screenshot collection log entries",
+ description = "Take a screenshot when completing an entry in the collection log",
+ position = 18,
+ section = whatSection
+ )
+ default boolean screenshotCollectionLogEntries()
+ {
+ return true;
+ }
+
@ConfigItem(
keyName = "hotkey",
name = "Screenshot hotkey",
description = "When you press this key a screenshot will be taken",
- position = 18
+ position = 19
)
default Keybind hotkey()
{
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java
index dbda81a49c..28449b69ca 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java
@@ -95,6 +95,7 @@ import net.runelite.client.util.Text;
@Slf4j
public class ScreenshotPlugin extends Plugin
{
+ private static final String COLLECTION_LOG_TEXT = "New item added to your collection log: ";
private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!";
private static final Map CHEST_LOOT_EVENTS = ImmutableMap.of(12127, "The Gauntlet");
private static final int GAUNTLET_REGION = 7512;
@@ -456,6 +457,13 @@ public class ScreenshotPlugin extends Plugin
takeScreenshot(fileName, "Duels");
}
}
+
+ if (config.screenshotCollectionLogEntries() && chatMessage.startsWith(COLLECTION_LOG_TEXT))
+ {
+ String entry = Text.removeTags(chatMessage).substring(COLLECTION_LOG_TEXT.length());
+ String fileName = "Collection log (" + entry + ")";
+ takeScreenshot(fileName, "Collection Log");
+ }
}
@Subscribe
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/Boss.java b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/Boss.java
index 295194a961..e0ba59d3d6 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/Boss.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/specialcounter/Boss.java
@@ -45,7 +45,8 @@ enum Boss
KING_BLACK_DRAGON(NpcID.KING_BLACK_DRAGON, NpcID.KING_BLACK_DRAGON_2642, NpcID.KING_BLACK_DRAGON_6502),
KRIL_TSUROTH(NpcID.KRIL_TSUTSAROTH, NpcID.KRIL_TSUTSAROTH_6495),
VENETENATIS(NpcID.VENENATIS, NpcID.VENENATIS_6610),
- VETION(NpcID.VETION, NpcID.VETION_REBORN);
+ VETION(NpcID.VETION, NpcID.VETION_REBORN),
+ ALCHEMICAL_HYDRA(NpcID.ALCHEMICAL_HYDRA, NpcID.ALCHEMICAL_HYDRA_8616, NpcID.ALCHEMICAL_HYDRA_8617, NpcID.ALCHEMICAL_HYDRA_8618, NpcID.ALCHEMICAL_HYDRA_8619, NpcID.ALCHEMICAL_HYDRA_8620, NpcID.ALCHEMICAL_HYDRA_8621, NpcID.ALCHEMICAL_HYDRA_8622, NpcID.ALCHEMICAL_HYDRA_8634);
private final Set ids;
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/BarRenderer.java b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/BarRenderer.java
index 84742e2f63..03cc2f326c 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/BarRenderer.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/statusbars/BarRenderer.java
@@ -25,12 +25,14 @@
*/
package net.runelite.client.plugins.statusbars;
-import lombok.RequiredArgsConstructor;
-import net.runelite.client.ui.FontManager;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
+import java.awt.Point;
import java.util.function.Supplier;
+import lombok.RequiredArgsConstructor;
+import net.runelite.client.ui.FontManager;
+import net.runelite.client.ui.overlay.components.TextComponent;
@RequiredArgsConstructor
class BarRenderer
@@ -100,28 +102,26 @@ class BarRenderer
private void renderIconsAndCounters(StatusBarsConfig config, Graphics2D graphics, int x, int y)
{
- graphics.setFont(FontManager.getRunescapeSmallFont());
- graphics.setColor(Color.WHITE);
- String counterText = Integer.toString(currentValue);
- final int widthOfCounter = graphics.getFontMetrics().stringWidth(counterText);
- int centerText = (WIDTH - PADDING) / 2 - (widthOfCounter / 2);
- final Image icon = iconSupplier.get();
+ final boolean skillIconEnabled = config.enableSkillIcon();
+
+ if (skillIconEnabled)
+ {
+ final Image icon = iconSupplier.get();
+ graphics.drawImage(icon, x + ICON_AND_COUNTER_OFFSET_X + PADDING, y + ICON_AND_COUNTER_OFFSET_Y - icon.getWidth(null), null);
+ }
if (config.enableCounter())
{
- if (config.enableSkillIcon())
- {
- graphics.drawImage(icon, x + ICON_AND_COUNTER_OFFSET_X + PADDING, y + ICON_AND_COUNTER_OFFSET_Y - icon.getWidth(null), null);
- graphics.drawString(counterText, x + centerText + PADDING, y + SKILL_ICON_HEIGHT);
- }
- else
- {
- graphics.drawString(counterText, x + centerText + PADDING, y + COUNTER_ICON_HEIGHT);
- }
- }
- else if (config.enableSkillIcon())
- {
- graphics.drawImage(icon, x + ICON_AND_COUNTER_OFFSET_X + PADDING, y + ICON_AND_COUNTER_OFFSET_Y - icon.getWidth(null), null);
+ graphics.setFont(FontManager.getRunescapeSmallFont());
+ final String counterText = Integer.toString(currentValue);
+ final int widthOfCounter = graphics.getFontMetrics().stringWidth(counterText);
+ final int centerText = (WIDTH - PADDING) / 2 - (widthOfCounter / 2);
+ final int yOffset = skillIconEnabled ? SKILL_ICON_HEIGHT : COUNTER_ICON_HEIGHT;
+
+ final TextComponent textComponent = new TextComponent();
+ textComponent.setText(counterText);
+ textComponent.setPosition(new Point(x + centerText + PADDING, y + yOffset));
+ textComponent.render(graphics);
}
}
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java
index 8b2fc1d187..d2e13ccad3 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java
@@ -131,7 +131,24 @@ public class WorldMapOverlay extends Overlay
if (worldPoint.isSnapToEdge())
{
- if (worldMapRectangle.contains(drawPoint.getX(), drawPoint.getY()))
+ // Get a smaller rect for edge-snapped icons so they display correctly at the edge
+ final Rectangle snappedRect = widget.getBounds();
+ snappedRect.grow(-image.getWidth() / 2, -image.getHeight() / 2);
+
+ final Rectangle unsnappedRect = new Rectangle(snappedRect);
+ if (worldPoint.getImagePoint() != null)
+ {
+ int dx = worldPoint.getImagePoint().getX() - (image.getWidth() / 2);
+ int dy = worldPoint.getImagePoint().getY() - (image.getHeight() / 2);
+ unsnappedRect.translate(dx, dy);
+ }
+ // Make the unsnap rect slightly smaller so a smaller snapped image doesn't cause a freak out
+ if (worldPoint.isCurrentlyEdgeSnapped())
+ {
+ unsnappedRect.grow(-image.getWidth(), -image.getHeight());
+ }
+
+ if (unsnappedRect.contains(drawPoint.getX(), drawPoint.getY()))
{
if (worldPoint.isCurrentlyEdgeSnapped())
{
@@ -141,7 +158,7 @@ public class WorldMapOverlay extends Overlay
}
else
{
- drawPoint = clipToRectangle(drawPoint, worldMapRectangle);
+ drawPoint = clipToRectangle(drawPoint, snappedRect);
if (!worldPoint.isCurrentlyEdgeSnapped())
{
worldPoint.setCurrentlyEdgeSnapped(true);
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlayMouseListener.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlayMouseListener.java
index 949c578ec2..71af9a55dc 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlayMouseListener.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlayMouseListener.java
@@ -60,6 +60,12 @@ public class WorldMapOverlayMouseListener extends MouseAdapter
if (SwingUtilities.isLeftMouseButton(e) && !worldMapPoints.isEmpty())
{
Point mousePos = client.getMouseCanvasPosition();
+ final Widget view = client.getWidget(WidgetInfo.WORLD_MAP_VIEW);
+
+ if (view == null)
+ {
+ return e;
+ }
for (WorldMapPoint worldMapPoint : worldMapPoints)
{
@@ -77,6 +83,7 @@ public class WorldMapOverlayMouseListener extends MouseAdapter
RenderOverview renderOverview = client.getRenderOverview();
renderOverview.setWorldMapPositionTarget(target);
}
+ e.consume();
return worldMapPoint.onClick(e);
}
}
diff --git a/runelite-client/src/test/java/net/runelite/client/config/ChatColorConfigTest.java b/runelite-client/src/test/java/net/runelite/client/config/ChatColorConfigTest.java
new file mode 100644
index 0000000000..e3b140fe34
--- /dev/null
+++ b/runelite-client/src/test/java/net/runelite/client/config/ChatColorConfigTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021, Adam
+ * 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.config;
+
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+public class ChatColorConfigTest
+{
+ @Test
+ public void testUniqueKeys()
+ {
+ final Set configKeyNames = new HashSet<>();
+
+ for (Method method : ChatColorConfig.class.getMethods())
+ {
+ final ConfigItem annotation = method.getAnnotation(ConfigItem.class);
+ if (annotation == null)
+ {
+ continue;
+ }
+
+ final String configKeyName = annotation.keyName();
+ if (configKeyNames.contains(configKeyName))
+ {
+ fail("keyName " + configKeyName + " is duplicated in " + ChatColorConfig.class);
+ }
+
+ configKeyNames.add(configKeyName);
+ }
+ }
+}
\ No newline at end of file
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 c089368bac..788437d165 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
@@ -157,7 +157,7 @@ public class ChatCommandsPluginTest
@Test
public void testTheatreOfBlood()
{
- ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: 5:04
Theatre of Blood wave completion time: 37:04 (Personal best!)", null, 0);
+ ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: 5:04
Theatre of Blood wave completion time: 37:04 (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: 73.", null, 0);
@@ -167,7 +167,7 @@ public class ChatCommandsPluginTest
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.0);
// Precise times
- ChatMessage chatMessagePrecise = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: 5:04
Theatre of Blood wave completion time: 37:04.20 (Personal best!)", null, 0);
+ ChatMessage chatMessagePrecise = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: 5:04
Theatre of Blood wave completion time: 37:04.20 (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessagePrecise);
chatCommandsPlugin.onChatMessage(chatMessageEvent);
@@ -194,6 +194,21 @@ public class ChatCommandsPluginTest
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.4);
}
+ @Test
+ public void testTheatreOfBloodStoryMode()
+ {
+ ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
+ "Theatre of Blood wave completion time: 5:04 (new personal best)
" +
+ "Theatre of Blood total completion time: 24:39 (new personal best)", null, 0);
+ chatCommandsPlugin.onChatMessage(chatMessage);
+
+ ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood: Story Mode count is: 73.", null, 0);
+ chatCommandsPlugin.onChatMessage(chatMessageEvent);
+
+ verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood story mode", 73);
+ verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood story mode", 5 * 60 + 4.0);
+ }
+
@Test
public void testWintertodt()
{
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClueTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClueTest.java
new file mode 100644
index 0000000000..f9ed47a555
--- /dev/null
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/cluescrolls/clues/ThreeStepCrypticClueTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020, Jordan Atwood
+ * 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.cluescrolls.clues;
+
+import com.google.common.base.Joiner;
+import net.runelite.api.coords.WorldPoint;
+import net.runelite.client.util.Text;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import org.junit.Test;
+
+public class ThreeStepCrypticClueTest
+{
+ @Test
+ public void forTextEmptyString()
+ {
+ assertNull(ThreeStepCrypticClue.forText("", ""));
+ }
+
+ @Test
+ public void nonNullLocations()
+ {
+ final String clueText = Joiner.on("
").join(CrypticClue.CLUES.stream().map(CrypticClue::getText).toArray());
+ final ThreeStepCrypticClue clue = ThreeStepCrypticClue.forText(Text.sanitizeMultilineText(clueText).toLowerCase(), clueText);
+
+ assertNotNull(clue);
+ for (final WorldPoint location : clue.getLocations())
+ {
+ assertNotNull(location);
+ }
+ }
+}
diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java
index 317515d053..d8e1ec0eaf 100644
--- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java
+++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java
@@ -86,6 +86,10 @@ public interface RSClient extends RSGameEngine, Client
@Override
int getMapAngle();
+ @Import("camAngleY")
+ @Override
+ void setCameraYawTarget(int cameraYawTarget);
+
@Import("Tiles_heights")
@Override
int[][][] getTileHeights();