diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityArenaTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityArenaTimer.java new file mode 100644 index 0000000000..3c6a493da5 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityArenaTimer.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, Alex Kolpa + * 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.agility; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.time.temporal.ChronoUnit; +import javax.imageio.ImageIO; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.ui.overlay.infobox.Timer; + +@Slf4j +public class AgilityArenaTimer extends Timer +{ + public AgilityArenaTimer(Plugin plugin) + { + super(1, ChronoUnit.MINUTES, getTicketImage(), plugin); + setTooltip("Time left until location changes"); + } + + private static BufferedImage image; + private static BufferedImage getTicketImage() + { + if (image != null) + { + return image; + } + + try + { + synchronized (ImageIO.class) + { + image = ImageIO.read(AgilityArenaTimer.class.getResourceAsStream( "agilityarenaticket.png")); + } + } + catch (IOException ex) + { + log.warn("unable to load image", ex); + } + + return image; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java index 5ce0d3ed1e..55945fb4bb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityConfig.java @@ -123,4 +123,26 @@ public interface AgilityConfig extends Config { return Color.RED; } + + @ConfigItem( + keyName = "agilityArenaNotifier", + name = "Agility Arena notifier", + description = "Notify on ticket location change in Agility Arena", + position = 9 + ) + default boolean notifyAgilityArena() + { + return true; + } + + @ConfigItem( + keyName = "agilityArenaTimer", + name = "Agility Arena timer", + description = "Configures whether Agility Arena timer is displayed", + position = 10 + ) + default boolean showAgilityArenaTimer() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java index 5726ce12dd..bcf56162f8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/agility/AgilityPlugin.java @@ -30,6 +30,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import javax.inject.Inject; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -41,6 +42,8 @@ import net.runelite.api.Node; import static net.runelite.api.Skill.AGILITY; import net.runelite.api.Tile; import net.runelite.api.TileObject; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.DecorativeObjectChanged; import net.runelite.api.events.DecorativeObjectDespawned; import net.runelite.api.events.DecorativeObjectSpawned; @@ -49,6 +52,7 @@ import net.runelite.api.events.GameObjectChanged; import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; import net.runelite.api.events.GroundObjectChanged; import net.runelite.api.events.GroundObjectDespawned; import net.runelite.api.events.GroundObjectSpawned; @@ -56,10 +60,12 @@ import net.runelite.api.events.ItemLayerChanged; import net.runelite.api.events.WallObjectChanged; import net.runelite.api.events.WallObjectDespawned; import net.runelite.api.events.WallObjectSpawned; +import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; @PluginDescriptor( name = "Agility" @@ -67,6 +73,8 @@ import net.runelite.client.ui.overlay.Overlay; @Slf4j public class AgilityPlugin extends Plugin { + private static final int AGILITY_ARENA_REGION_ID = 11157; + @Getter private final Map obstacles = new HashMap<>(); @@ -80,9 +88,15 @@ public class AgilityPlugin extends Plugin @Inject private LapCounterOverlay lapOverlay; + @Inject + private Notifier notifier; + @Inject private Client client; + @Inject + private InfoBoxManager infoBoxManager; + @Inject private AgilityConfig config; @@ -90,6 +104,7 @@ public class AgilityPlugin extends Plugin private AgilitySession session; private int lastAgilityXp; + private WorldPoint lastArenaTicketPosition; @Provides AgilityConfig getConfig(ConfigManager configManager) @@ -119,11 +134,29 @@ public class AgilityPlugin extends Plugin case HOPPING: case LOGIN_SCREEN: session = null; + lastArenaTicketPosition = null; + removeAgilityArenaTimer(); break; case LOADING: markOfGrace = null; obstacles.clear(); break; + case LOGGED_IN: + if (!isInAgilityArena()) + { + lastArenaTicketPosition = null; + removeAgilityArenaTimer(); + } + break; + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!config.showAgilityArenaTimer()) + { + removeAgilityArenaTimer(); } } @@ -204,6 +237,49 @@ public class AgilityPlugin extends Plugin return false; } + @Subscribe + public void onGameTick(GameTick tick) + { + if (isInAgilityArena()) + { + WorldPoint newTicketPosition = client.getHintArrowPoint(); + if (!Objects.equals(lastArenaTicketPosition, newTicketPosition)) + { + // We don't want to notify when players first enter the course + if (lastArenaTicketPosition != null) + { + if (config.notifyAgilityArena()) + { + notifier.notify("Ticket location changed"); + } + + if (config.showAgilityArenaTimer()) + { + showNewAgilityArenaTimer(); + } + } + + lastArenaTicketPosition = newTicketPosition; + } + } + } + + private boolean isInAgilityArena() + { + return AGILITY_ARENA_REGION_ID == client.getLocalPlayer().getWorldLocation().getRegionID(); + } + + private void removeAgilityArenaTimer() + { + infoBoxManager.removeIf(infoBox -> infoBox instanceof AgilityArenaTimer); + } + + private void showNewAgilityArenaTimer() + { + removeAgilityArenaTimer(); + infoBoxManager.addInfoBox(new AgilityArenaTimer(this)); + } + @Subscribe public void onGameObjectSpawned(GameObjectSpawned event) { diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/agility/agilityarenaticket.png b/runelite-client/src/main/resources/net/runelite/client/plugins/agility/agilityarenaticket.png new file mode 100644 index 0000000000..55b841db97 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/agility/agilityarenaticket.png differ