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

@@ -25,7 +25,7 @@
object ProjectVersions { object ProjectVersions {
const val launcherVersion = "2.2.0" 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" const val openosrsVersion = "4.8.1"

View File

@@ -673,12 +673,19 @@ public interface Client extends GameEngine
boolean isMenuOpen(); 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 * @return the map angle
*/ */
int getMapAngle(); int getMapAngle();
/**
* Set the target camera yaw
*
* @param cameraYawTarget
*/
void setCameraYawTarget(int cameraYawTarget);
/** /**
* Checks whether the client window is currently resized. * Checks whether the client window is currently resized.
* *

View File

@@ -185,7 +185,7 @@ public interface ChatColorConfig extends Config
@ConfigItem( @ConfigItem(
position = 14, position = 14,
keyName = "opaqueClanChatMessageHighlight", keyName = "opaqueClanMessageHighlight",
name = "Clan chat message highlight", name = "Clan chat message highlight",
description = "Color of highlights in Clan Chat messages", description = "Color of highlights in Clan Chat messages",
section = opaqueSection section = opaqueSection
@@ -582,7 +582,7 @@ public interface ChatColorConfig extends Config
@ConfigItem( @ConfigItem(
position = 64, position = 64,
keyName = "transparentClanChatMessageHighlight", keyName = "transparentClanMessageHighlight",
name = "Clan chat message highlight (transparent)", name = "Clan chat message highlight (transparent)",
description = "Color of highlights in Clan Chat messages (transparent)", description = "Color of highlights in Clan Chat messages (transparent)",
section = transparentSection section = transparentSection

View File

@@ -448,7 +448,7 @@ public class ConfigManager
public void setConfiguration(String groupName, String profile, String key, @NonNull String value) 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(); throw new IllegalArgumentException();
} }

View File

@@ -191,4 +191,15 @@ public interface CameraConfig extends Config
{ {
return false; 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.BeforeRender;
import net.runelite.api.events.ClientTick; import net.runelite.api.events.ClientTick;
import net.runelite.api.events.FocusChanged; import net.runelite.api.events.FocusChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.ScriptPreFired; 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 * Whether or not the current menu has any non-ignored menu entries
*/ */
private boolean menuHasEntries; private boolean menuHasEntries;
private int savedCameraYaw;
@Inject @Inject
private Client client; 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 * 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 * 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 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_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 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 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 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\\)"); 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); configManager.setRSProfileConfiguration("killcount", boss.toLowerCase(), killcount);
} }
private void unsetKc(String boss)
{
configManager.unsetRSProfileConfiguration("killcount", boss.toLowerCase());
}
private int getKc(String boss) private int getKc(String boss)
{ {
Integer killCount = configManager.getRSProfileConfiguration("killcount", boss.toLowerCase(), int.class); Integer killCount = configManager.getRSProfileConfiguration("killcount", boss.toLowerCase(), int.class);
@@ -256,6 +261,11 @@ public class ChatCommandsPlugin extends Plugin
configManager.setRSProfileConfiguration("personalbest", boss.toLowerCase(), seconds); configManager.setRSProfileConfiguration("personalbest", boss.toLowerCase(), seconds);
} }
private void unsetPb(String boss)
{
configManager.unsetRSProfileConfiguration("personalbest", boss.toLowerCase());
}
private double getPb(String boss) private double getPb(String boss)
{ {
Double personalBest = configManager.getRSProfileConfiguration("personalbest", boss.toLowerCase(), double.class); Double personalBest = configManager.getRSProfileConfiguration("personalbest", boss.toLowerCase(), double.class);
@@ -280,19 +290,30 @@ public class ChatCommandsPlugin extends Plugin
String boss = matcher.group(1); String boss = matcher.group(1);
int kc = Integer.parseInt(matcher.group(2)); 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 // We either already have the pb, or need to remember the boss for the upcoming pb
if (lastPb > -1) if (lastPb > -1)
{ {
log.debug("Got out-of-order personal best for {}: {}", boss, lastPb); log.debug("Got out-of-order personal best for {}: {}", renamedBoss, lastPb);
setPb(boss, lastPb); setPb(renamedBoss, lastPb);
lastPb = -1; lastPb = -1;
} }
else else
{ {
lastBossKill = boss; lastBossKill = renamedBoss;
lastBossTime = client.getTickCount(); lastBossTime = client.getTickCount();
} }
return; return;
@@ -1687,6 +1708,19 @@ public class ChatCommandsPlugin extends Plugin
case "raids 2": case "raids 2":
return "Theatre of Blood"; 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 // agility course
case "prif": case "prif":
case "prifddinas": case "prifddinas":

View File

@@ -330,6 +330,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
private final String text; private final String text;
private final String npc; private final String npc;
private final int objectId; private final int objectId;
@Nullable
private final WorldPoint location; private final WorldPoint location;
private final String solution; private final String solution;
@Nullable @Nullable
@@ -371,7 +372,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
this(text, npc, objectId, location, solution, null); 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.text = text;
this.npc = npc; this.npc = npc;

View File

@@ -30,6 +30,7 @@ import java.util.AbstractMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.runelite.api.InventoryID; import net.runelite.api.InventoryID;
@@ -167,6 +168,7 @@ public class ThreeStepCrypticClue extends ClueScroll implements TextClueScroll,
return clueSteps.stream() return clueSteps.stream()
.filter(s -> !s.getValue()) .filter(s -> !s.getValue())
.map(s -> s.getKey().getLocation()) .map(s -> s.getKey().getLocation())
.filter(Objects::nonNull)
.toArray(WorldPoint[]::new); .toArray(WorldPoint[]::new);
} }

View File

@@ -199,7 +199,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private int vboUiHandle; private int vboUiHandle;
private int fboSceneHandle; private int fboSceneHandle;
private int texSceneHandle;
private int rboSceneHandle; private int rboSceneHandle;
// scene vertex buffer // scene vertex buffer
@@ -297,7 +296,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
{ {
try try
{ {
texSceneHandle = fboSceneHandle = rboSceneHandle = -1; // AA FBO fboSceneHandle = rboSceneHandle = -1; // AA FBO
unorderedModels = smallModels = largeModels = 0; unorderedModels = smallModels = largeModels = 0;
drawingModel = false; 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.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, aaSamples, gl.GL_RGBA, width, height);
gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, rboSceneHandle); 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 // Reset
gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, 0);
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0); gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0);
gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0); gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0);
} }
private void shutdownAAFbo() private void shutdownAAFbo()
{ {
if (texSceneHandle != -1)
{
glDeleteTexture(gl, texSceneHandle);
texSceneHandle = -1;
}
if (fboSceneHandle != -1) if (fboSceneHandle != -1)
{ {
glDeleteFrameBuffer(gl, fboSceneHandle); glDeleteFrameBuffer(gl, fboSceneHandle);

View File

@@ -110,6 +110,13 @@ public class IdleNotifierPlugin extends Plugin
return configManager.getConfig(IdleNotifierConfig.class); 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 @Subscribe
public void onAnimationChanged(AnimationChanged event) public void onAnimationChanged(AnimationChanged event)
{ {

View File

@@ -419,6 +419,17 @@ public interface MenuEntrySwapperConfig extends Config
return false; 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( @ConfigItem(
keyName = "swapAbyssTeleport", keyName = "swapAbyssTeleport",
name = "Teleport to Abyss", 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 10", () -> shiftModifier() && config.shopSell() == SellMode.SELL_10);
swap("value", "sell 50", () -> shiftModifier() && config.shopSell() == SellMode.SELL_50); swap("value", "sell 50", () -> shiftModifier() && config.shopSell() == SellMode.SELL_50);
swap("wear", "tele to poh", config::swapTeleToPoh);
swap("wear", "rub", config::swapTeleportItem); swap("wear", "rub", config::swapTeleportItem);
swap("wear", "teleport", config::swapTeleportItem); swap("wear", "teleport", config::swapTeleportItem);
swap("wield", "teleport", config::swapTeleportItem); swap("wield", "teleport", config::swapTeleportItem);

View File

@@ -96,6 +96,7 @@ public class AlchemyRoom extends MTARoom
private AlchemyItem best; private AlchemyItem best;
private Cupboard suggestion; private Cupboard suggestion;
private boolean hintSet;
@Inject @Inject
private AlchemyRoom(Client client, MTAConfig config, MTAPlugin plugin, ItemManager itemManager, InfoBoxManager infoBoxManager) private AlchemyRoom(Client client, MTAConfig config, MTAPlugin plugin, ItemManager itemManager, InfoBoxManager infoBoxManager)
@@ -221,6 +222,11 @@ public class AlchemyRoom extends MTARoom
if (!inside()) if (!inside())
{ {
reset(); reset();
if (hintSet)
{
client.clearHintArrow();
hintSet = false;
}
} }
} }
} }
@@ -381,6 +387,7 @@ public class AlchemyRoom extends MTARoom
{ {
client.setHintArrow(object.getWorldLocation()); client.setHintArrow(object.getWorldLocation());
found = true; found = true;
hintSet = true;
} }
BufferedImage image = itemManager.getImage(alchemyItem.getId()); BufferedImage image = itemManager.getImage(alchemyItem.getId());
@@ -395,6 +402,7 @@ public class AlchemyRoom extends MTARoom
if (!found && suggestion != null) if (!found && suggestion != null)
{ {
client.setHintArrow(suggestion.gameObject.getWorldLocation()); client.setHintArrow(suggestion.gameObject.getWorldLocation());
hintSet = true;
} }
} }

View File

@@ -50,6 +50,7 @@ public class EnchantmentRoom extends MTARoom
private final Client client; private final Client client;
private final List<WorldPoint> dragonstones = new ArrayList<>(); private final List<WorldPoint> dragonstones = new ArrayList<>();
private boolean hintSet;
@Inject @Inject
private EnchantmentRoom(MTAConfig config, Client client) private EnchantmentRoom(MTAConfig config, Client client)
@@ -64,6 +65,11 @@ public class EnchantmentRoom extends MTARoom
if (gameStateChanged.getGameState() == GameState.LOADING) if (gameStateChanged.getGameState() == GameState.LOADING)
{ {
dragonstones.clear(); dragonstones.clear();
if (hintSet)
{
client.clearHintArrow();
hintSet = false;
}
} }
} }
@@ -79,10 +85,12 @@ public class EnchantmentRoom extends MTARoom
if (nearest != null) if (nearest != null)
{ {
client.setHintArrow(nearest); client.setHintArrow(nearest);
hintSet = true;
} }
else else
{ {
client.clearHintArrow(); client.clearHintArrow();
hintSet = false;
} }
} }

View File

@@ -253,11 +253,23 @@ public interface ScreenshotConfig extends Config
return false; 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( @ConfigItem(
keyName = "hotkey", keyName = "hotkey",
name = "Screenshot hotkey", name = "Screenshot hotkey",
description = "When you press this key a screenshot will be taken", description = "When you press this key a screenshot will be taken",
position = 18 position = 19
) )
default Keybind hotkey() default Keybind hotkey()
{ {

View File

@@ -95,6 +95,7 @@ import net.runelite.client.util.Text;
@Slf4j @Slf4j
public class ScreenshotPlugin extends Plugin 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 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 Map<Integer, String> CHEST_LOOT_EVENTS = ImmutableMap.of(12127, "The Gauntlet");
private static final int GAUNTLET_REGION = 7512; private static final int GAUNTLET_REGION = 7512;
@@ -456,6 +457,13 @@ public class ScreenshotPlugin extends Plugin
takeScreenshot(fileName, "Duels"); 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 @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), 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), KRIL_TSUROTH(NpcID.KRIL_TSUTSAROTH, NpcID.KRIL_TSUTSAROTH_6495),
VENETENATIS(NpcID.VENENATIS, NpcID.VENENATIS_6610), 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; private final Set<Integer> ids;

View File

@@ -25,12 +25,14 @@
*/ */
package net.runelite.client.plugins.statusbars; package net.runelite.client.plugins.statusbars;
import lombok.RequiredArgsConstructor;
import net.runelite.client.ui.FontManager;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.Point;
import java.util.function.Supplier; import java.util.function.Supplier;
import lombok.RequiredArgsConstructor;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.components.TextComponent;
@RequiredArgsConstructor @RequiredArgsConstructor
class BarRenderer class BarRenderer
@@ -100,28 +102,26 @@ class BarRenderer
private void renderIconsAndCounters(StatusBarsConfig config, Graphics2D graphics, int x, int y) private void renderIconsAndCounters(StatusBarsConfig config, Graphics2D graphics, int x, int y)
{ {
graphics.setFont(FontManager.getRunescapeSmallFont()); final boolean skillIconEnabled = config.enableSkillIcon();
graphics.setColor(Color.WHITE);
String counterText = Integer.toString(currentValue); if (skillIconEnabled)
final int widthOfCounter = graphics.getFontMetrics().stringWidth(counterText); {
int centerText = (WIDTH - PADDING) / 2 - (widthOfCounter / 2); final Image icon = iconSupplier.get();
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.enableCounter())
{ {
if (config.enableSkillIcon()) graphics.setFont(FontManager.getRunescapeSmallFont());
{ final String counterText = Integer.toString(currentValue);
graphics.drawImage(icon, x + ICON_AND_COUNTER_OFFSET_X + PADDING, y + ICON_AND_COUNTER_OFFSET_Y - icon.getWidth(null), null); final int widthOfCounter = graphics.getFontMetrics().stringWidth(counterText);
graphics.drawString(counterText, x + centerText + PADDING, y + SKILL_ICON_HEIGHT); final int centerText = (WIDTH - PADDING) / 2 - (widthOfCounter / 2);
} final int yOffset = skillIconEnabled ? SKILL_ICON_HEIGHT : COUNTER_ICON_HEIGHT;
else
{ final TextComponent textComponent = new TextComponent();
graphics.drawString(counterText, x + centerText + PADDING, y + COUNTER_ICON_HEIGHT); textComponent.setText(counterText);
} textComponent.setPosition(new Point(x + centerText + PADDING, y + yOffset));
} textComponent.render(graphics);
else if (config.enableSkillIcon())
{
graphics.drawImage(icon, x + ICON_AND_COUNTER_OFFSET_X + PADDING, y + ICON_AND_COUNTER_OFFSET_Y - icon.getWidth(null), null);
} }
} }

View File

@@ -131,7 +131,24 @@ public class WorldMapOverlay extends Overlay
if (worldPoint.isSnapToEdge()) 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()) if (worldPoint.isCurrentlyEdgeSnapped())
{ {
@@ -141,7 +158,7 @@ public class WorldMapOverlay extends Overlay
} }
else else
{ {
drawPoint = clipToRectangle(drawPoint, worldMapRectangle); drawPoint = clipToRectangle(drawPoint, snappedRect);
if (!worldPoint.isCurrentlyEdgeSnapped()) if (!worldPoint.isCurrentlyEdgeSnapped())
{ {
worldPoint.setCurrentlyEdgeSnapped(true); worldPoint.setCurrentlyEdgeSnapped(true);

View File

@@ -60,6 +60,12 @@ public class WorldMapOverlayMouseListener extends MouseAdapter
if (SwingUtilities.isLeftMouseButton(e) && !worldMapPoints.isEmpty()) if (SwingUtilities.isLeftMouseButton(e) && !worldMapPoints.isEmpty())
{ {
Point mousePos = client.getMouseCanvasPosition(); Point mousePos = client.getMouseCanvasPosition();
final Widget view = client.getWidget(WidgetInfo.WORLD_MAP_VIEW);
if (view == null)
{
return e;
}
for (WorldMapPoint worldMapPoint : worldMapPoints) for (WorldMapPoint worldMapPoint : worldMapPoints)
{ {
@@ -77,6 +83,7 @@ public class WorldMapOverlayMouseListener extends MouseAdapter
RenderOverview renderOverview = client.getRenderOverview(); RenderOverview renderOverview = client.getRenderOverview();
renderOverview.setWorldMapPositionTarget(target); renderOverview.setWorldMapPositionTarget(target);
} }
e.consume();
return worldMapPoint.onClick(e); 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 @Test
public void testTheatreOfBlood() 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); chatCommandsPlugin.onChatMessage(chatMessage);
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0); 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); verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.0);
// Precise times // 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(chatMessagePrecise);
chatCommandsPlugin.onChatMessage(chatMessageEvent); chatCommandsPlugin.onChatMessage(chatMessageEvent);
@@ -194,6 +194,21 @@ public class ChatCommandsPluginTest
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.4); 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 @Test
public void testWintertodt() 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);
}
}
}

View File

@@ -86,6 +86,10 @@ public interface RSClient extends RSGameEngine, Client
@Override @Override
int getMapAngle(); int getMapAngle();
@Import("camAngleY")
@Override
void setCameraYawTarget(int cameraYawTarget);
@Import("Tiles_heights") @Import("Tiles_heights")
@Override @Override
int[][][] getTileHeights(); int[][][] getTileHeights();