From 419bbeec11c4104f14cf51c107404f37e49e5b48 Mon Sep 17 00:00:00 2001 From: Seth Date: Tue, 30 Jan 2018 17:39:22 -0600 Subject: [PATCH] runecraft plugin: add Abyss rifts overlay --- .../plugins/runecraft/AbyssOverlay.java | 193 ++++++++++++++++++ .../client/plugins/runecraft/AbyssRifts.java | 87 ++++++++ .../plugins/runecraft/RunecraftConfig.java | 140 +++++++++++++ .../plugins/runecraft/RunecraftPlugin.java | 64 +++++- 4 files changed, 479 insertions(+), 5 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java new file mode 100644 index 0000000000..16c089fd72 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssOverlay.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016-2018, Seth + * 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.runecraft; + +import com.google.inject.Inject; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import net.runelite.api.Client; +import net.runelite.api.DecorativeObject; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.client.game.ItemManager; +import static net.runelite.client.plugins.runecraft.AbyssRifts.AIR_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.BLOOD_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.BODY_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.CHAOS_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.COSMIC_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.DEATH_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.EARTH_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.FIRE_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.LAW_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.MIND_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.NATURE_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.SOUL_RIFT; +import static net.runelite.client.plugins.runecraft.AbyssRifts.WATER_RIFT; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; + +class AbyssOverlay extends Overlay +{ + private static final int MAX_DISTANCE = 2350; + private static final Dimension IMAGE_SIZE = new Dimension(15, 14); + + private final Set rifts = new HashSet<>(); + private final Map abyssIcons = new HashMap<>(); + + private final Client client; + private final RunecraftPlugin plugin; + private final RunecraftConfig config; + + @Inject + private ItemManager itemManager; + + @Inject + AbyssOverlay(Client client, RunecraftPlugin plugin, RunecraftConfig config) + { + setPosition(OverlayPosition.DYNAMIC); + this.client = client; + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics, java.awt.Point parent) + { + if (!config.showRifts()) + { + return null; + } + + Point localLocation = client.getLocalPlayer().getLocalLocation(); + for (DecorativeObject object : plugin.getAbyssObjects()) + { + Point location = object.getLocalLocation(); + if (localLocation.distanceTo(location) <= MAX_DISTANCE) + { + renderRifts(graphics, object); + } + } + + return null; + } + + private void renderRifts(Graphics2D graphics, DecorativeObject object) + { + AbyssRifts rift = AbyssRifts.getRift(object.getId()); + if (rift == null || !rifts.contains(rift)) + { + return; + } + + BufferedImage image = getImage(rift); + Point miniMapImage = Perspective.getMiniMapImageLocation(client, object.getLocalLocation(), image); + + if (miniMapImage != null) + { + graphics.drawImage(image, miniMapImage.getX(), miniMapImage.getY(), null); + } + } + + public BufferedImage getImage(AbyssRifts rift) + { + BufferedImage image = abyssIcons.get(rift); + if (image != null) + { + return image; + } + + // Since item image is too big, we must resize it first. + image = itemManager.getImage(rift.getItemId()); + BufferedImage resizedImage = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = resizedImage.createGraphics(); + g.drawImage(image, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null); + g.dispose(); + + abyssIcons.put(rift, resizedImage); + return resizedImage; + } + + public void updateConfig() + { + rifts.clear(); + if (config.showAir()) + { + rifts.add(AIR_RIFT); + } + if (config.showBlood()) + { + rifts.add(BLOOD_RIFT); + } + if (config.showBody()) + { + rifts.add(BODY_RIFT); + } + if (config.showChaos()) + { + rifts.add(CHAOS_RIFT); + } + if (config.showCosmic()) + { + rifts.add(COSMIC_RIFT); + } + if (config.showDeath()) + { + rifts.add(DEATH_RIFT); + } + if (config.showEarth()) + { + rifts.add(EARTH_RIFT); + } + if (config.showFire()) + { + rifts.add(FIRE_RIFT); + } + if (config.showLaw()) + { + rifts.add(LAW_RIFT); + } + if (config.showMind()) + { + rifts.add(MIND_RIFT); + } + if (config.showNature()) + { + rifts.add(NATURE_RIFT); + } + if (config.showSoul()) + { + rifts.add(SOUL_RIFT); + } + if (config.showWater()) + { + rifts.add(WATER_RIFT); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java new file mode 100644 index 0000000000..60f02d5080 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/AbyssRifts.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016-2018, Seth + * 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.runecraft; + +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import static net.runelite.api.ItemID.AIR_RUNE; +import static net.runelite.api.ItemID.BLOOD_RUNE; +import static net.runelite.api.ItemID.BODY_RUNE; +import static net.runelite.api.ItemID.CHAOS_RUNE; +import static net.runelite.api.ItemID.COSMIC_RUNE; +import static net.runelite.api.ItemID.DEATH_RUNE; +import static net.runelite.api.ItemID.EARTH_RUNE; +import static net.runelite.api.ItemID.FIRE_RUNE; +import static net.runelite.api.ItemID.LAW_RUNE; +import static net.runelite.api.ItemID.MIND_RUNE; +import static net.runelite.api.ItemID.NATURE_RUNE; +import static net.runelite.api.ItemID.SOUL_RUNE; +import static net.runelite.api.ItemID.WATER_RUNE; +import net.runelite.api.ObjectID; + +public enum AbyssRifts +{ + AIR_RIFT(ObjectID.AIR_RIFT, AIR_RUNE), + BLOOD_RIFT(ObjectID.BLOOD_RIFT, BLOOD_RUNE), + BODY_RIFT(ObjectID.BODY_RIFT, BODY_RUNE), + CHAOS_RIFT(ObjectID.CHAOS_RIFT, CHAOS_RUNE), + COSMIC_RIFT(ObjectID.COSMIC_RIFT, COSMIC_RUNE), + DEATH_RIFT(ObjectID.DEATH_RIFT, DEATH_RUNE), + EARTH_RIFT(ObjectID.EARTH_RIFT, EARTH_RUNE), + FIRE_RIFT(ObjectID.FIRE_RIFT, FIRE_RUNE), + LAW_RIFT(ObjectID.LAW_RIFT, LAW_RUNE), + MIND_RIFT(ObjectID.MIND_RIFT, MIND_RUNE), + NATURE_RIFT(ObjectID.NATURE_RIFT, NATURE_RUNE), + SOUL_RIFT(ObjectID.SOUL_RIFT, SOUL_RUNE), + WATER_RIFT(ObjectID.WATER_RIFT, WATER_RUNE); + + @Getter + private final int objectId; + + @Getter + private final int itemId; + + private static final Map rifts = new HashMap<>(); + + static + { + for (AbyssRifts s : values()) + { + rifts.put(s.getObjectId(), s); + } + } + + AbyssRifts(int objectId, int itemId) + { + this.objectId = objectId; + this.itemId = itemId; + } + + public static AbyssRifts getRift(int id) + { + return rifts.get(id); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java index 6d1c0f30c4..53d2fa3161 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftConfig.java @@ -55,4 +55,144 @@ public interface RunecraftConfig extends Config { return true; } + + @ConfigItem( + keyName = "showRifts", + name = "Show Rifts in Abyss", + description = "Configures whether the rifts in the abyss will be displayed" + ) + default boolean showRifts() + { + return true; + } + + @ConfigItem( + keyName = "showAir", + name = "Show Air rift", + description = "Configures whether to display the air rift" + ) + default boolean showAir() + { + return true; + } + + @ConfigItem( + keyName = "showBlood", + name = "Show Blood rift", + description = "Configures whether to display the Blood rift" + ) + default boolean showBlood() + { + return true; + } + + @ConfigItem( + keyName = "showBody", + name = "Show Body rift", + description = "Configures whether to display the Body rift" + ) + default boolean showBody() + { + return true; + } + + @ConfigItem( + keyName = "showChaos", + name = "Show Chaos rift", + description = "Configures whether to display the Chaos rift" + ) + default boolean showChaos() + { + return true; + } + + @ConfigItem( + keyName = "showCosmic", + name = "Show Cosmic rift", + description = "Configures whether to display the Cosmic rift" + ) + default boolean showCosmic() + { + return true; + } + + @ConfigItem( + keyName = "showDeath", + name = "Show Death rift", + description = "Configures whether to display the Death rift" + ) + default boolean showDeath() + { + return true; + } + + @ConfigItem( + keyName = "showEarth", + name = "Show Earth rift", + description = "Configures whether to display the Earth rift" + ) + default boolean showEarth() + { + return true; + } + + @ConfigItem( + keyName = "showFire", + name = "Show Fire rift", + description = "Configures whether to display the Fire rift" + ) + default boolean showFire() + { + return true; + } + + @ConfigItem( + keyName = "showLaw", + name = "Show Law rift", + description = "Configures whether to display the Law rift" + ) + default boolean showLaw() + { + return true; + } + + @ConfigItem( + keyName = "showMind", + name = "Show Mind rift", + description = "Configures whether to display the Mind rift" + ) + default boolean showMind() + { + return true; + } + + @ConfigItem( + keyName = "showNature", + name = "Show Nature rift", + description = "Configures whether to display the Nature rift" + ) + default boolean showNature() + { + return true; + } + + @ConfigItem( + keyName = "showSoul", + name = "Show Soul rift", + description = "Configures whether to display the Soul rift" + ) + default boolean showSoul() + { + return true; + } + + @ConfigItem( + keyName = "showWater", + name = "Show Water rift", + description = "Configures whether to display the Water rift" + ) + default boolean showWater() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java index 64a04542dc..be556b7cbe 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runecraft/RunecraftPlugin.java @@ -29,12 +29,22 @@ import com.google.inject.Binder; import com.google.inject.Provides; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; import net.runelite.api.ChatMessageType; -import net.runelite.client.config.ConfigManager; +import net.runelite.api.DecorativeObject; +import net.runelite.api.GameState; import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.DecorativeObjectDespawned; +import net.runelite.api.events.DecorativeObjectSpawned; +import net.runelite.api.events.GameStateChanged; +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; @@ -46,11 +56,17 @@ public class RunecraftPlugin extends Plugin { private static Pattern bindNeckString = Pattern.compile("You have ([0-9]+) charges left before your Binding necklace disintegrates."); - @Inject - RunecraftOverlay overlay; + @Getter(AccessLevel.PACKAGE) + private final Set abyssObjects = new HashSet<>(); @Inject - BindNeckOverlay bindNeckOverlay; + private RunecraftOverlay overlay; + + @Inject + private BindNeckOverlay bindNeckOverlay; + + @Inject + private AbyssOverlay abyssOverlay; @Override public void configure(Binder binder) @@ -67,7 +83,19 @@ public class RunecraftPlugin extends Plugin @Override public Collection getOverlays() { - return Arrays.asList(overlay, bindNeckOverlay); + return Arrays.asList(overlay, bindNeckOverlay, abyssOverlay); + } + + @Override + protected void startUp() throws Exception + { + abyssOverlay.updateConfig(); + } + + @Subscribe + public void updateConfig(ConfigChanged event) + { + abyssOverlay.updateConfig(); } @Subscribe @@ -105,4 +133,30 @@ public class RunecraftPlugin extends Plugin bindNeckOverlay.bindingCharges = 17; } } + + @Subscribe + public void onDecorativeObjectSpawn(DecorativeObjectSpawned event) + { + DecorativeObject decorativeObject = event.getDecorativeObject(); + if (AbyssRifts.getRift(decorativeObject.getId()) != null) + { + abyssObjects.add(decorativeObject); + } + } + + @Subscribe + public void onDecorativeObjectDespawned(DecorativeObjectDespawned event) + { + DecorativeObject decorativeObject = event.getDecorativeObject(); + abyssObjects.remove(decorativeObject); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOADING) + { + abyssObjects.clear(); + } + } }