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

This commit is contained in:
ThatGamerBlue
2021-06-10 04:05:42 +01:00
25 changed files with 327 additions and 57 deletions

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + COX_TEAM_SIZES + "</col> Duration:</col> <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)</col>");
private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + COX_TEAM_SIZES + "</col> Duration:</col> <col=ff0000>[0-9:.]+</col> Personal best: </col><col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col>");
private static final Pattern TOB_WAVE_PB_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(Personal best!\\)");
private static final Pattern TOB_WAVE_PB_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)");
private static final Pattern TOB_WAVE_DURATION_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>[0-9:.]+</col><br></col>Personal best: (?<pb>[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in) <col=[0-9a-f]{6}>[0-9:.]+</col>\\. Personal best: (?:<col=ff0000>)?(?<pb>[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?i)^(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in) <col=[0-9a-f]{6}>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(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":

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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",

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -50,6 +50,7 @@ public class EnchantmentRoom extends MTARoom
private final Client client;
private final List<WorldPoint> 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;
}
}

View File

@@ -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()
{

View File

@@ -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<Integer, String> 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

View File

@@ -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<Integer> ids;

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.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<String> 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);
}
}
}

View File

@@ -157,7 +157,7 @@ public class ChatCommandsPluginTest
@Test
public void testTheatreOfBlood()
{
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>37:04</col> (Personal best!)", null, 0);
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>37:04</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", 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: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>37:04.20</col> (Personal best!)", null, 0);
ChatMessage chatMessagePrecise = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>37:04.20</col> (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: <col=ff0000>5:04</col> (new personal best)<br>" +
"Theatre of Blood total completion time: <col=ff0000>24:39</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood: Story Mode count is: <col=ff0000>73</col>.", 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()
{

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2020, Jordan Atwood <jordan.atwood423@gmail.com>
* 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("<br><br>").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);
}
}
}