runelite-client: remove volcanic mine plugin

It has been deemed to be against the game rules, and removal requested by Jagex.
This commit is contained in:
Adam
2018-01-25 11:27:34 -05:00
parent 155dfb7c63
commit 638029d5ba
6 changed files with 0 additions and 1124 deletions

View File

@@ -1,65 +0,0 @@
/*
* Copyright (c) 2017, 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.plugins.volcanicmine;
import java.time.Duration;
public enum LavaPlatform
{
STAGE_1(30998, 90),
STAGE_2(30999, 45),
STAGE_3(31000, 5);
private final int objectId;
private final Duration time;
LavaPlatform(int objectId, int time)
{
this.objectId = objectId;
this.time = Duration.ofSeconds(time);
}
public int getObjectId()
{
return objectId;
}
public Duration getTime()
{
return time;
}
public static LavaPlatform fromId(int id)
{
for (LavaPlatform lavaPlatform : values())
{
if (lavaPlatform.objectId == id)
{
return lavaPlatform;
}
}
return null;
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright (c) 2017. l2-
*
* 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.volcanicmine;
import com.google.common.collect.ImmutableSet;
import net.runelite.api.Point;
import java.util.Set;
class OptimalPaths
{
private static final int INSTANCE_SIZE = 192;
private static final Set<Point> OPTIMAL_PATH_POINTS = ImmutableSet.of(
new Point(161, 145),
new Point(161, 144),
new Point(161, 143),
new Point(161, 142),
new Point(169, 151),
new Point(169, 148),
new Point(169, 147),
new Point(169, 133),
new Point(175, 146),
new Point(176, 146),
new Point(179, 116),
new Point(179, 117),
new Point(179, 118),
new Point(167, 101),
new Point(167, 100),
new Point(167, 104),
new Point(167, 105),
new Point(166, 76),
new Point(166, 77),
new Point(166, 78),
new Point(166, 79),
new Point(146, 107),
new Point(145, 107),
new Point(144, 107),
new Point(143, 107),
new Point(142, 107),
new Point(141, 107),
new Point(139, 104),
new Point(139, 103),
new Point(139, 102),
new Point(139, 101),
new Point(152, 101),
new Point(152, 100),
new Point(149, 76)
);
public final static Set<Point> BOULDER_RANGE_POINTS = ImmutableSet.of(
new Point(162, 123),
new Point(161, 152),
new Point(160, 151),
new Point(163, 105),
new Point(163, 104),
new Point(163, 103),
new Point(163, 102),
new Point(163, 101),
new Point(164, 92),
new Point(164, 91),
new Point(164, 90),
new Point(164, 83),
new Point(165, 80),
new Point(164, 80),
new Point(155, 80),
new Point(155, 81),
new Point(155, 82),
new Point(155, 83),
new Point(155, 89),
new Point(155, 90),
new Point(155, 91),
new Point(155, 92),
new Point(156, 103),
new Point(156, 104),
new Point(156, 105),
new Point(162, 126),
new Point(162, 125),
new Point(162, 124)
);
//only use global location
public static boolean isOptimalPathTile(Point point)
{
Point instanceLocation = new Point(point.getX() % INSTANCE_SIZE, point.getY() % INSTANCE_SIZE);
return OPTIMAL_PATH_POINTS.contains(instanceLocation);
}
//only use global location
public static boolean isBoulderRangeTile(Point point)
{
Point instanceLocation = new Point(point.getX() % INSTANCE_SIZE, point.getY() % INSTANCE_SIZE);
return BOULDER_RANGE_POINTS.contains(instanceLocation);
}
}

View File

@@ -1,226 +0,0 @@
/*
* Copyright (c) 2017. l2-
*
* 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.volcanicmine;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "VolcanicMine",
name = "Volcanic mine",
description = "Configuration for the volcanic mine plugin"
)
public interface VolcanicMineConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "enabled",
name = "Enable",
description = "Configures whether the volcanic mine plugin is displayed"
)
default boolean enabled()
{
return true;
}
@ConfigItem(
position = 1,
keyName = "tray",
name = "Send Tray Notification",
description = "Toggles tray notifications"
)
default boolean sendTrayNotification()
{
return true;
}
@ConfigItem(
position = 2,
keyName = "focused",
name = "Alert When Focused",
description = "Toggles idle notifications for when the client is focused"
)
default boolean alertWhenFocused()
{
return true;
}
@ConfigItem(
position = 3,
keyName = "request",
name = "Request Window Focus",
description = "Toggles window focus request"
)
default boolean requestFocus()
{
return true;
}
@ConfigItem(
position = 4,
keyName = "prayerHelper",
name = "shows prayer",
description = "Shows when you need to use protection prayers"
)
default boolean prayerHelperEnabled()
{
return true;
}
@ConfigItem(
position = 5,
keyName = "timerOverlay",
name = "timer overlay",
description = "The overlay showing the timers"
)
default boolean timerOverlay()
{
return true;
}
@ConfigItem(
position = 6,
keyName = "optimalPathOverlay",
name = "show optimal Paths",
description = "The overlay showing the optimal paths"
)
default boolean optimalPaths()
{
return true;
}
@ConfigItem(
position = 7,
keyName = "platformColorLow",
name = "PlatformColor low risk",
description = "Configures the color for the platformOverlay"
)
default Color platformColorLow()
{
return Color.GREEN;
}
@ConfigItem(
position = 8,
keyName = "platformColorMed",
name = "PlatformColor med risk",
description = "Configures the color for the platformOverlay"
)
default Color platformColorMed()
{
return Color.YELLOW;
}
@ConfigItem(
position = 9,
keyName = "platformColorHigh",
name = "PlatformColor high risk",
description = "Configures the color for the platformOverlay"
)
default Color platformColorHigh()
{
return Color.decode("#FF3333");
}
@ConfigItem(
position = 10,
keyName = "platformTimerThreshold",
name = "Platform timer notification threshold",
description = "At what time does the plugin notify (in seconds), set to -1 to disable"
)
default int platformTimerThreshold()
{
return 20;
}
@ConfigItem(
position = 11,
keyName = "timeLeftThreshold",
name = "Time left threshold",
description = "At what time does the plugin notify (in seconds), set to -1 to disable"
)
default int timerThreshold()
{
return 40;
}
@ConfigItem(
position = 12,
keyName = "stabilityThreshold",
name = "Stability threshold",
description = "At what stability does the plugin notify (in percentage), set to -1 to disable"
)
default int stabilityPercentageThreshold()
{
return 30;
}
@ConfigItem(
position = 13,
keyName = "prayer",
name = "Prayer warning",
description = "Protect prayer warning setting"
)
default WarningMode prayerWarning()
{
return WarningMode.INGAME_AND_NOTIFICATION;
}
@ConfigItem(
position = 14,
keyName = "hotTiles",
name = "Hot Tile warning",
description = "Hot tile warning setting"
)
default WarningMode hotTileWarning()
{
return WarningMode.INGAME_AND_NOTIFICATION;
}
@ConfigItem(
position = 15,
keyName = "timerWarning",
name = "timer warning",
description = "timer low warning setting"
)
default WarningMode timerWarning()
{
return WarningMode.INGAME_AND_NOTIFICATION;
}
@ConfigItem(
position = 16,
keyName = "stabilityWarning",
name = "stability warning",
description = "stability low warning setting"
)
default WarningMode stabilityWarning()
{
return WarningMode.INGAME_AND_NOTIFICATION;
}
}

View File

@@ -1,245 +0,0 @@
/*
* Copyright (c) 2017. l2-
*
* 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.volcanicmine;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.time.Instant;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.Prayer;
import net.runelite.api.Region;
import net.runelite.api.Tile;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil;
@Slf4j
public class VolcanicMineOverlay extends Overlay
{
private static final int THRESH_LOW = 45;
private static final int THRESH_MED = 5;
private static final int MAX_DISTANCE = 19; //2400/128 rounded up
private static final int REGION_SIZE = 104;
private static final int Z_OFFSET_TIMER = 25;
private static final String PROTECT_MESSAGE = "Protect!";
private final VolcanicMinePlugin plugin;
private final VolcanicMineConfig config;
private final Client client;
private Image protectFromMissilesImg;
@Inject
VolcanicMineOverlay(@Nullable Client client, VolcanicMinePlugin plugin, VolcanicMineConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.UNDER_WIDGETS);
this.client = client;
this.plugin = plugin;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics, java.awt.Point point)
{
if (!plugin.getInside() || !config.enabled())
{
return null;
}
renderTileObjects(graphics);
renderRangePrayer(graphics);
return null;
}
private void renderRangePrayer(Graphics2D graphics)
{
if (client.getViewportWidget() == null || !plugin.getDrawRangePray() || !config.prayerHelperEnabled())
{
return;
}
Image protectFromMissiles = getProtectFromMissilesImage();
if (protectFromMissiles == null)
{
return;
}
Rectangle viewport = client.getViewportWidget().getBounds();
Rectangle stringBounds = graphics.getFontMetrics().getStringBounds(PROTECT_MESSAGE, graphics).getBounds();
int x = (int) (viewport.getX() + viewport.getWidth());
int y = (int) (viewport.getY() + viewport.getHeight());
int width = (int) stringBounds.getWidth() + 6;
int height = (int) (protectFromMissiles.getHeight(null) + stringBounds.getHeight()) + 5;
Rectangle rectangle = new Rectangle(x - width, y - height, width, height);
graphics.setColor(new Color(255, 255, 255, 150));
graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
graphics.setColor(client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES) ? Color.GREEN : Color.WHITE);
graphics.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
graphics.drawImage(protectFromMissiles, x - protectFromMissiles.getWidth(null) - 10, y - protectFromMissiles.getHeight(null) - 15, null);
graphics.drawString(PROTECT_MESSAGE, x - (int) stringBounds.getWidth() - 2, y);
}
//this is less efficient than drawing from the map however this is more accurate as it doesn't draw false positives (tiles which are not in the current region).
private void renderTileObjects(Graphics2D graphics)
{
Region region = client.getRegion();
Tile[][][] tiles = region.getTiles();
int z = client.getPlane();
for (int x = 0; x < REGION_SIZE; ++x)
{
for (int y = 0; y < REGION_SIZE; ++y)
{
Tile tile = tiles[z][x][y];
if (tile == null)
{
continue;
}
renderPaths(graphics, tile);
renderGameObjects(graphics, tile);
}
}
}
private void renderPaths(Graphics2D graphics, Tile tile)
{
if (config.optimalPaths() && !plugin.getObjectTimerMap().containsKey(tile))
{
Point worldLoc = tile.getWorldLocation();
if (client.getLocalPlayer().getWorldLocation().distanceTo(worldLoc) > MAX_DISTANCE)
{
return;
}
if (OptimalPaths.isOptimalPathTile(worldLoc))
{
Point localTile = tile.getLocalLocation();
localTile = new Point(localTile.getX() + Perspective.LOCAL_TILE_SIZE / 2, localTile.getY() + Perspective.LOCAL_TILE_SIZE / 2);
Polygon poly = Perspective.getCanvasTilePoly(client, localTile);
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, Color.CYAN);
}
}
else if (OptimalPaths.isBoulderRangeTile(worldLoc))
{
Point localTile = tile.getLocalLocation();
localTile = new Point(localTile.getX() + Perspective.LOCAL_TILE_SIZE / 2, localTile.getY() + Perspective.LOCAL_TILE_SIZE / 2);
Polygon poly = Perspective.getCanvasTilePoly(client, localTile);
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, Color.MAGENTA);
}
}
}
}
private void renderGameObjects(Graphics2D graphics, Tile tile)
{
GameObject[] gameObjects = tile.getGameObjects();
if (gameObjects == null)
{
return;
}
for (GameObject gameObject : gameObjects)
{
if (gameObject != null && plugin.getObjectTimerMap().containsKey(tile) && config.timerOverlay())
{
Duration duration = Duration.between(Instant.now(), plugin.getObjectTimerMap().get(tile));
if (!duration.isNegative())
{
long seconds = duration.getSeconds();
int minutes = (int) seconds / 60;
String text = String.format("%d:%02d", minutes, seconds % 60); // format as m:ss
Color color;
if (seconds > THRESH_LOW)
{
color = config.platformColorLow();
}
else if (seconds > THRESH_MED)
{
color = config.platformColorMed();
}
else
{
color = config.platformColorHigh();
}
Point location = gameObject.getCanvasTextLocation(graphics, text, Z_OFFSET_TIMER);
if (location != null)
{
OverlayUtil.renderTextLocation(graphics, location, text, color);
return; //only 1 timer per tile
}
}
}
}
}
public Image getProtectFromMissilesImage()
{
if (protectFromMissilesImg == null)
{
String path = "/prayers/protect_from_missiles.png";
protectFromMissilesImg = getImage(path);
}
return protectFromMissilesImg;
}
private Image getImage(String path)
{
Image image = null;
try
{
InputStream in = VolcanicMineOverlay.class.getResourceAsStream(path);
image = ImageIO.read(in);
}
catch (IOException e)
{
log.warn("Error loading image", e);
}
return image;
}
}

View File

@@ -1,424 +0,0 @@
/*
* Copyright (c) 2017. l2-
*
* 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.volcanicmine;
import static java.lang.Math.abs;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Binder;
import com.google.inject.Provides;
import java.awt.Color;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.Prayer;
import net.runelite.api.Query;
import net.runelite.api.Region;
import net.runelite.api.Tile;
import net.runelite.api.queries.NPCQuery;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.api.events.ConfigChanged;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.task.Schedule;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.util.QueryRunner;
@PluginDescriptor(
name = "Volcanic mine helper"
)
@Slf4j
public class VolcanicMinePlugin extends Plugin
{
private static final int REGION_SIZE = 104;
private static final int MAX_DISTANCE = 2400;
private static final int LAVA_ID = 30997;
private static final int LAVA_BEAST_ATTACK_RANGE = 1400;
private static final int GAS_CHAMBER_ROCK_ID = 31045;
private static final int GAS_CHAMBER_NO_ROCK_ID = 31046;
private static final int GAS_CHAMBER_ROCK_RESPAWN_TIMER = 15;
private static final String LAVA_BEAST = "Lava beast";
private static final Pattern coltagPattern = Pattern.compile("((<col=([0-f]){6}>)|(<\\/col>))");
@Inject
Client client;
@Inject
ClientUI clientUI;
@Inject
QueryRunner queryRunner;
@Inject
Notifier notifier;
@Inject
VolcanicMineConfig config;
@Inject
VolcanicMineOverlay overlay;
private Map<Tile, Instant> objectTimerMap = new HashMap<>();
private boolean drawRangePray = false;
private boolean isAboutToFall = false;
private boolean isAboutToCollapse = false;
private boolean timerRunningLow = false;
private boolean isInside = false;
private int stabilityPercentageThreshold;
@Override
public void configure(Binder binder)
{
binder.bind(VolcanicMineOverlay.class);
}
@Provides
VolcanicMineConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(VolcanicMineConfig.class);
}
@Override
protected void startUp() throws Exception
{
if (config.stabilityPercentageThreshold() >= -1 && config.stabilityPercentageThreshold() <= 100)
{
stabilityPercentageThreshold = config.stabilityPercentageThreshold();
}
}
public Boolean getInside()
{
return isInside;
}
public VolcanicMineConfig getConfig()
{
return config;
}
public Map<Tile, Instant> getObjectTimerMap()
{
return objectTimerMap;
}
public Boolean getDrawRangePray()
{
return drawRangePray;
}
@Override
public Overlay getOverlay()
{
return overlay;
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (config.stabilityPercentageThreshold() >= -1 && config.stabilityPercentageThreshold() <= 100)
{
stabilityPercentageThreshold = config.stabilityPercentageThreshold();
}
}
@Schedule(
period = 600,
unit = ChronoUnit.MILLIS
)
public void update()
{
if (client.getGameState() != GameState.LOGGED_IN || !config.enabled())
{
return;
}
isInside = isInside();
if (!isInside)
{
return;
}
lookForGameObjects();
cleanMap();
//-- it is unlikely more than 1 of the following notifications will be triggered in 1 update call.
//-- it is possible so maybe send 1 notification per update max which contains the message(s)?
//check if in range of a lava beast
boolean lastRangePray = drawRangePray;
drawRangePray = lavaBeastInRange(client.getLocalPlayer());
if (!client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES) && drawRangePray && !lastRangePray)
{
warnPlayer(config.prayerWarning(), "Turn on prayer!");
}
//check if about to fall into lava
boolean lastIsAboutToFall = isAboutToFall;
isAboutToFall = isAboutToFall(client.getLocalPlayer().getLocalLocation());
if (isAboutToFall && !lastIsAboutToFall)
{
warnPlayer(config.hotTileWarning(), "Watch out for the lava!");
}
//check if timer is about to run out
boolean lastTimerRunningLow = timerRunningLow;
timerRunningLow = isTimerRunningLow();
if (timerRunningLow && !lastTimerRunningLow)
{
warnPlayer(config.timerWarning(), "Time to bail!");
}
//check if stability is low
boolean lastIsAboutToCollapse = isAboutToCollapse;
isAboutToCollapse = isAboutToCollapse();
if (isAboutToCollapse && !lastIsAboutToCollapse)
{
warnPlayer(config.stabilityWarning(), "Stability is low!");
}
}
private boolean isAboutToCollapse()
{
Widget widget = client.getWidget(WidgetInfo.VOLCANICMINE_STABILITY);
if (widget != null && !widget.isHidden())
{
try
{
if (Integer.parseInt(removeColTags(widget.getText().replace("%", ""))) < stabilityPercentageThreshold) //sanitize of col tags
{
return true;
}
}
catch (NumberFormatException ex)
{
log.debug("Failed to retrieve stability percentage", ex);
}
}
return false;
}
private boolean isTimerRunningLow()
{
Widget widget = client.getWidget(WidgetInfo.VOLCANICMINE_TIME_LEFT);
if (widget != null && !widget.isHidden())
{
try
{
if (timeToSeconds(widget.getText()) < config.timerThreshold())
{
return true;
}
}
catch (NumberFormatException ex)
{
log.debug("Failed to retrieve time left", ex);
}
}
return false;
}
private boolean isAboutToFall(Point point)
{
Instant now = Instant.now();
for (Tile tile : objectTimerMap.keySet())
{
if (tile.getGameObjects() != null
&& tile.getGameObjects()[0] != null
&& tile.getGameObjects()[0].getLocalLocation().equals(point)
&& objectTimerMap.get(tile).isAfter(now) //in case the entry hasn't been removed from the hashmap, ignore.
&& Duration.between(now, objectTimerMap.get(tile)).getSeconds() < config.platformTimerThreshold())
{
return true;
}
}
return false;
}
private boolean isInside()
{
Widget widget = client.getWidget(WidgetInfo.VOLCANICMINE_GENERAL_INFOBOX_GROUP);
return widget != null && !widget.isHidden() && client.getPlane() == 1;
}
private boolean lavaBeastInRange(Player player)
{
Query query = new NPCQuery()
.nameEquals(LAVA_BEAST)
.isWithinArea(player.getLocalLocation(), LAVA_BEAST_ATTACK_RANGE);
NPC[] npcs = queryRunner.runQuery(query);
return npcs.length > 0;
}
private void warnPlayer(WarningMode warningMode, String warning)
{
if (warningMode == WarningMode.INGAME || warningMode == WarningMode.INGAME_AND_NOTIFICATION)
{
client.sendGameMessage(ChatMessageType.GAME, getColTag(config.platformColorHigh()) + "Volcanic Mine helper: " + warning);
}
if (warningMode == WarningMode.NOTIFICATION || warningMode == WarningMode.INGAME_AND_NOTIFICATION)
{
sendNotification(warning);
}
}
private void sendNotification(String message)
{
if (!config.alertWhenFocused() && clientUI.isFocused())
{
return;
}
if (config.requestFocus())
{
clientUI.requestFocus();
}
if (config.sendTrayNotification())
{
notifier.notify(message);
}
}
private void lookForGameObjects()
{
Player player = client.getLocalPlayer();
Region region = client.getRegion();
Tile[][][] tiles = region.getTiles();
int z = client.getPlane();
for (int x = 0; x < REGION_SIZE; ++x)
{
for (int y = 0; y < REGION_SIZE; ++y)
{
Tile tile = tiles[z][x][y];
if (tile == null)
{
continue;
}
lookForGameObjects(tile, player);
}
}
}
private void lookForGameObjects(Tile tile, Player player)
{
Point playerLocation = player.getLocalLocation();
GameObject[] gameObjects = tile.getGameObjects();
if (gameObjects == null)
{
return;
}
for (GameObject gameObject : gameObjects)
{
if (gameObject == null)
{
continue;
}
Point objectLocation = gameObject.getLocalLocation();
if (abs(playerLocation.getX() - objectLocation.getX()) < MAX_DISTANCE
&& abs(playerLocation.getY() - objectLocation.getY()) < MAX_DISTANCE)
{
LavaPlatform lavaPlatform = LavaPlatform.fromId(gameObject.getId());
Instant now = Instant.now();
Instant vanishTime;
if (lavaPlatform != null)
{
vanishTime = now.plus(lavaPlatform.getTime());
}
else if (gameObject.getId() == GAS_CHAMBER_NO_ROCK_ID)
{
vanishTime = now.plus(Duration.ofSeconds(GAS_CHAMBER_ROCK_RESPAWN_TIMER));
}
else
{
continue;
}
Instant returnInstant = objectTimerMap.putIfAbsent(tile, vanishTime);
if (returnInstant != null)
{
if (returnInstant.isBefore(now)
|| vanishTime.isBefore(returnInstant))
{
objectTimerMap.replace(tile, vanishTime);
}
}
}
}
}
private void cleanMap()
{
//remove the timers which hit 0
objectTimerMap = objectTimerMap.entrySet().stream()
.filter(entry -> Instant.now().isBefore(entry.getValue()))
.filter(v -> v.getKey().getGameObjects() != null && v.getKey().getGameObjects()[0] != null && v.getKey().getGameObjects()[0].getId() != LAVA_ID && v.getKey().getGameObjects()[0].getId() != GAS_CHAMBER_ROCK_ID)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
}
public static int timeToSeconds(String s) throws NumberFormatException
{
String[] time = s.split(":", 2);
if (time.length < 2)
{
return Integer.parseInt(time[0]);
}
return Integer.parseInt(time[0]) * 60 + Integer.parseInt(time[1]);
}
public static String getColTag(Color color)
{
return color == null ? "" : "<col=" + Integer.toHexString(color.getRGB() & 0xFFFFFF) + ">";
}
public static String removeColTags(String s)
{
StringBuffer result = new StringBuffer();
Matcher m = coltagPattern.matcher(s);
while (m.find())
{
m.appendReplacement(result, "");
}
m.appendTail(result);
return result.toString();
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (c) 2017. l2-
*
* 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.volcanicmine;
public enum WarningMode
{
OFF("Off"),
INGAME("Ingame message"),
NOTIFICATION("Windows notification"),
INGAME_AND_NOTIFICATION("Ingame & notification");
private final String name;
WarningMode(String name)
{
this.name = name;
}
@Override
public String toString()
{
return name;
}
}