poh, questlist, skybox, wiki, worldhopper, worldmap, zalcano
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@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.poh;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
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.components.ProgressPieComponent;
|
||||
|
||||
class BurnerOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final PohConfig config;
|
||||
private final PohPlugin plugin;
|
||||
|
||||
@Inject
|
||||
private BurnerOverlay(Client client, PohConfig config, PohPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!config.showBurner())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
plugin.getIncenseBurners().forEach((tile, burner) ->
|
||||
{
|
||||
if (tile.getPlane() != client.getPlane())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PohPlugin.BURNER_LIT.contains(burner.getId()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Instant now = Instant.now();
|
||||
final long startCountdown = Duration.between(burner.getStart(), now).getSeconds();
|
||||
final double certainSec = burner.getCountdownTimer() - startCountdown;
|
||||
|
||||
long endCountdown = 0;
|
||||
|
||||
if (certainSec <= 0)
|
||||
{
|
||||
if (burner.getEnd() == null)
|
||||
{
|
||||
burner.setEnd(Instant.now());
|
||||
}
|
||||
|
||||
endCountdown = Duration.between(burner.getEnd(), now).getSeconds();
|
||||
}
|
||||
|
||||
final double randomSec = burner.getRandomTimer() - endCountdown;
|
||||
final ProgressPieComponent pieComponent = new ProgressPieComponent();
|
||||
final Point loc = Perspective.localToCanvas(client, tile.getLocalLocation(), tile.getPlane());
|
||||
|
||||
if (loc == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pieComponent.setPosition(loc);
|
||||
|
||||
if (certainSec > 0)
|
||||
{
|
||||
pieComponent.setProgress(certainSec / burner.getCountdownTimer());
|
||||
pieComponent.setFill(Color.GREEN);
|
||||
pieComponent.setBorderColor(Color.GREEN);
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
else if (randomSec > 0)
|
||||
{
|
||||
pieComponent.setProgress(randomSec / burner.getRandomTimer());
|
||||
pieComponent.setFill(Color.ORANGE);
|
||||
pieComponent.setBorderColor(Color.ORANGE);
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@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.poh;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
class IncenseBurner
|
||||
{
|
||||
private final Instant start = Instant.now();
|
||||
private final int id;
|
||||
private double countdownTimer;
|
||||
private double randomTimer;
|
||||
private Instant end;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@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.poh;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("poh")
|
||||
public interface PohConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showPortals",
|
||||
name = "Show Portals",
|
||||
description = "Configures whether to display teleport portals"
|
||||
)
|
||||
default boolean showPortals()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showAltar",
|
||||
name = "Show Altar",
|
||||
description = "Configures whether or not the altar is displayed"
|
||||
)
|
||||
default boolean showAltar()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showGlory",
|
||||
name = "Show Glory mount",
|
||||
description = "Configures whether or not the mounted glory is displayed"
|
||||
)
|
||||
default boolean showGlory()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showPools",
|
||||
name = "Show Pools",
|
||||
description = "Configures whether or not the pools are displayed"
|
||||
)
|
||||
default boolean showPools()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showRepairStand",
|
||||
name = "Show Repair stand",
|
||||
description = "Configures whether or not the repair stand is displayed"
|
||||
)
|
||||
default boolean showRepairStand()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showExitPortal",
|
||||
name = "Show Exit portal",
|
||||
description = "Configures whether or not the exit portal is displayed"
|
||||
)
|
||||
default boolean showExitPortal()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showBurner",
|
||||
name = "Show Incense Burner timers",
|
||||
description = "Configures whether or not unlit/lit burners are displayed"
|
||||
)
|
||||
default boolean showBurner()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showSpellbook",
|
||||
name = "Show Spellbook altar",
|
||||
description = "Configures whether or not the Spellbook altar is displayed"
|
||||
)
|
||||
default boolean showSpellbook()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showJewelleryBox",
|
||||
name = "Show Jewellery Box",
|
||||
description = "Configures whether or not the jewellery box is displayed"
|
||||
)
|
||||
default boolean showJewelleryBox()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMagicTravel",
|
||||
name = "Show Fairy/ Spirit Tree/ Obelisk",
|
||||
description = "Configures whether or not the Fairy ring, Spirit tree or Obelisk is displayed"
|
||||
)
|
||||
default boolean showMagicTravel()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showPortalNexus",
|
||||
name = "Show Portal Nexus",
|
||||
description = "Configures whether or not the Portal Nexus is displayed"
|
||||
)
|
||||
default boolean showPortalNexus()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showDigsitePendant",
|
||||
name = "Show Digsite Pendant",
|
||||
description = "Configures whether or not the Digsite Pendant is displayed"
|
||||
)
|
||||
default boolean showDigsitePendant()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showXericsTalisman",
|
||||
name = "Show Xeric's Talisman",
|
||||
description = "Configures whether or not the Xeric's Talisman is displayed"
|
||||
)
|
||||
default boolean showXericsTalisman()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMythicalCape",
|
||||
name = "Show Mythical Cape",
|
||||
description = "Configures whether or not the Mythical Cape is displayed"
|
||||
)
|
||||
default boolean showMythicalCape()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@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.poh;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import static net.runelite.api.NullObjectID.*;
|
||||
import static net.runelite.api.ObjectID.*;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
public enum PohIcons
|
||||
{
|
||||
EXITPORTAL("exitportal", PORTAL_4525),
|
||||
VARROCK("varrock", NULL_13615, NULL_13622, NULL_13629),
|
||||
FALADOR("falador", FALADOR_PORTAL, FALADOR_PORTAL_13624, FALADOR_PORTAL_13631),
|
||||
LUMBRIDGE("lumbridge", LUMBRIDGE_PORTAL, LUMBRIDGE_PORTAL_13623, LUMBRIDGE_PORTAL_13630),
|
||||
ARDOUGNE("ardougne", ARDOUGNE_PORTAL, ARDOUGNE_PORTAL_13626, ARDOUGNE_PORTAL_13633),
|
||||
YANILLE("yanille", NULL_13620, NULL_13627, NULL_13634),
|
||||
CAMELOT("camelot", NULL_13618, NULL_13625, NULL_13632),
|
||||
LUNARISLE("lunarisle", LUNAR_ISLE_PORTAL, LUNAR_ISLE_PORTAL_29347, LUNAR_ISLE_PORTAL_29355),
|
||||
WATERBIRTH("waterbirth", WATERBIRTH_ISLAND_PORTAL, WATERBIRTH_ISLAND_PORTAL_29350, WATERBIRTH_ISLAND_PORTAL_29358),
|
||||
FISHINGGUILD("fishingguild", FISHING_GUILD_PORTAL, FISHING_GUILD_PORTAL_29351, FISHING_GUILD_PORTAL_29359),
|
||||
SENNTISTEN("senntisten", SENNTISTEN_PORTAL, SENNTISTEN_PORTAL_29348, SENNTISTEN_PORTAL_29356),
|
||||
KHARYLL("kharyll", KHARYRLL_PORTAL, KHARYRLL_PORTAL_29346, KHARYRLL_PORTAL_29354),
|
||||
ANNAKARL("annakarl", ANNAKARL_PORTAL, ANNAKARL_PORTAL_29349, ANNAKARL_PORTAL_29357),
|
||||
KOUREND("kourend", KOUREND_PORTAL, KOUREND_PORTAL_29353, KOUREND_PORTAL_29361),
|
||||
MARIM("marim", MARIM_PORTAL, MARIM_PORTAL_29352, MARIM_PORTAL_29360),
|
||||
TROLLSTRONGHOLD("trollstronghold", TROLL_STRONGHOLD_PORTAL, TROLL_STRONGHOLD_PORTAL_33180, TROLL_STRONGHOLD_PORTAL_33181),
|
||||
GHORROCK("ghorrock", GHORROCK_PORTAL, GHORROCK_PORTAL_33436, GHORROCK_PORTAL_33439),
|
||||
CARRALLANGAR("carrallangar", CARRALLANGAR_PORTAL, CARRALLANGAR_PORTAL_33437, CARRALLANGAR_PORTAL_33440),
|
||||
CATHERBY("catherby", CATHERBY_PORTAL, CATHERBY_PORTAL_33435, CATHERBY_PORTAL_33438),
|
||||
WEISS("weiss", WEISS_PORTAL, WEISS_PORTAL_37593, WEISS_PORTAL_37605),
|
||||
APEATOLLDUNGEON("apeatolldungeon", APE_ATOLL_DUNGEON_PORTAL, APE_ATOLL_DUNGEON_PORTAL_37604, APE_ATOLL_DUNGEON_PORTAL_37616),
|
||||
BARROWS("barrows", BARROWS_PORTAL, BARROWS_PORTAL_37603, BARROWS_PORTAL_37615),
|
||||
BATTLEFRONT("battlefront", BATTLEFRONT_PORTAL, BATTLEFRONT_PORTAL_37596, BATTLEFRONT_PORTAL_37608),
|
||||
CEMETERY("cemetery", CEMETERY_PORTAL, CEMETERY_PORTAL_37602, CEMETERY_PORTAL_37614),
|
||||
DRAYNORMANOR("draynormanor", DRAYNOR_MANOR_PORTAL, DRAYNOR_MANOR_PORTAL_37595, DRAYNOR_MANOR_PORTAL_37607),
|
||||
FENKENSTRAINSCASTLE("fenkenstrainscastle", FENKENSTRAINS_CASTLE_PORTAL, FENKENSTRAINS_CASTLE_PORTAL_37599, FENKENSTRAINS_CASTLE_PORTAL_37611),
|
||||
HARMONYISLAND("harmonyisland", HARMONY_ISLAND_PORTAL, HARMONY_ISLAND_PORTAL_37601, HARMONY_ISLAND_PORTAL_37613),
|
||||
LUMBRIDGEGRAVEYARD("lumbridgegraveyard", LUMBRIDGE_GRAVEYARD_PORTAL, LUMBRIDGE_GRAVEYARD_PORTAL_37594, LUMBRIDGE_GRAVEYARD_PORTAL_37606),
|
||||
MINDALTAR("mindaltar", MIND_ALTAR_PORTAL, MIND_ALTAR_PORTAL_37597, MIND_ALTAR_PORTAL_37609),
|
||||
SALVEGRAVEYARD("salvegraveyard", SALVE_GRAVEYARD_PORTAL, SALVE_GRAVEYARD_PORTAL_37598, SALVE_GRAVEYARD_PORTAL_37610),
|
||||
WESTARDOUGNE("westardougne", WEST_ARDOUGNE_PORTAL, WEST_ARDOUGNE_PORTAL_37600, WEST_ARDOUGNE_PORTAL_37612),
|
||||
ALTAR("altar",
|
||||
ALTAR_13179, ALTAR_13180, ALTAR_13181, ALTAR_13182, ALTAR_13183, ALTAR_13184, ALTAR_13185, ALTAR_13186,
|
||||
ALTAR_13187, ALTAR_13188, ALTAR_13189, ALTAR_13190, ALTAR_13191, ALTAR_13192, ALTAR_13193, ALTAR_13194,
|
||||
ALTAR_13196, ALTAR_13197, ALTAR_13198, ALTAR_13199
|
||||
),
|
||||
POOLS("pool", POOL_OF_RESTORATION, POOL_OF_REVITALISATION, POOL_OF_REJUVENATION, FANCY_POOL_OF_REJUVENATION, ORNATE_POOL_OF_REJUVENATION),
|
||||
GLORY("glory", AMULET_OF_GLORY),
|
||||
REPAIR("repair", ARMOUR_REPAIR_STAND),
|
||||
SPELLBOOKALTAR("spellbook", ANCIENT_ALTAR, LUNAR_ALTAR, DARK_ALTAR, NULL_29150),
|
||||
JEWELLERYBOX("jewellery", NULL_29154, NULL_29155, NULL_29156),
|
||||
MAGICTRAVEL("transportation", SPIRIT_TREE_29227, NULL_29228, NULL_29229, OBELISK_31554),
|
||||
PORTALNEXUS("portalnexus",
|
||||
PORTAL_NEXUS, PORTAL_NEXUS_33355, PORTAL_NEXUS_33356, PORTAL_NEXUS_33357, PORTAL_NEXUS_33358, PORTAL_NEXUS_33359, PORTAL_NEXUS_33360,
|
||||
PORTAL_NEXUS_33361, PORTAL_NEXUS_33362, PORTAL_NEXUS_33363, PORTAL_NEXUS_33364, PORTAL_NEXUS_33365, PORTAL_NEXUS_33366, PORTAL_NEXUS_33367,
|
||||
PORTAL_NEXUS_33368, PORTAL_NEXUS_33369, PORTAL_NEXUS_33370, PORTAL_NEXUS_33371, PORTAL_NEXUS_33372, PORTAL_NEXUS_33373, PORTAL_NEXUS_33374,
|
||||
PORTAL_NEXUS_33375, PORTAL_NEXUS_33376, PORTAL_NEXUS_33377, PORTAL_NEXUS_33378, PORTAL_NEXUS_33379, PORTAL_NEXUS_33380, PORTAL_NEXUS_33381,
|
||||
PORTAL_NEXUS_33382, PORTAL_NEXUS_33383, PORTAL_NEXUS_33384, PORTAL_NEXUS_33385, PORTAL_NEXUS_33386, PORTAL_NEXUS_33387, PORTAL_NEXUS_33388,
|
||||
PORTAL_NEXUS_33389, PORTAL_NEXUS_33390, PORTAL_NEXUS_33391, PORTAL_NEXUS_33392, PORTAL_NEXUS_33393, PORTAL_NEXUS_33394, PORTAL_NEXUS_33395,
|
||||
PORTAL_NEXUS_33396, PORTAL_NEXUS_33397, PORTAL_NEXUS_33398, PORTAL_NEXUS_33399, PORTAL_NEXUS_33400, PORTAL_NEXUS_33401, PORTAL_NEXUS_33402,
|
||||
PORTAL_NEXUS_33403, PORTAL_NEXUS_33404, PORTAL_NEXUS_33405, PORTAL_NEXUS_33406, PORTAL_NEXUS_33407, PORTAL_NEXUS_33408, PORTAL_NEXUS_33409,
|
||||
PORTAL_NEXUS_33410, PORTAL_NEXUS_33423, PORTAL_NEXUS_33424, PORTAL_NEXUS_33425, PORTAL_NEXUS_33426, PORTAL_NEXUS_33427, PORTAL_NEXUS_33428,
|
||||
PORTAL_NEXUS_33429, PORTAL_NEXUS_33430, PORTAL_NEXUS_33431, PORTAL_NEXUS_37547, PORTAL_NEXUS_37548, PORTAL_NEXUS_37549, PORTAL_NEXUS_37550,
|
||||
PORTAL_NEXUS_37551, PORTAL_NEXUS_37552, PORTAL_NEXUS_37553, PORTAL_NEXUS_37554, PORTAL_NEXUS_37555, PORTAL_NEXUS_37556, PORTAL_NEXUS_37557,
|
||||
PORTAL_NEXUS_37558, PORTAL_NEXUS_37559, PORTAL_NEXUS_37560, PORTAL_NEXUS_37561, PORTAL_NEXUS_37562, PORTAL_NEXUS_37563, PORTAL_NEXUS_37564,
|
||||
PORTAL_NEXUS_37565, PORTAL_NEXUS_37566, PORTAL_NEXUS_37567, PORTAL_NEXUS_37568, PORTAL_NEXUS_37569, PORTAL_NEXUS_37570, PORTAL_NEXUS_37571,
|
||||
PORTAL_NEXUS_37572, PORTAL_NEXUS_37573, PORTAL_NEXUS_37574, PORTAL_NEXUS_37575, PORTAL_NEXUS_37576, PORTAL_NEXUS_37577, PORTAL_NEXUS_37578,
|
||||
PORTAL_NEXUS_37579, PORTAL_NEXUS_37580
|
||||
),
|
||||
XERICSTALISMAN("xericstalisman",
|
||||
XERICS_TALISMAN, XERICS_TALISMAN_33412, XERICS_TALISMAN_33413, XERICS_TALISMAN_33414, XERICS_TALISMAN_33415, XERICS_TALISMAN_33419
|
||||
),
|
||||
DIGSITEPENDANT("digsitependant",
|
||||
DIGSITE_PENDANT, DIGSITE_PENDANT_33417, DIGSITE_PENDANT_33418, DIGSITE_PENDANT_33420
|
||||
),
|
||||
MYTHICALCAPE("mythicalcape", MYTHICAL_CAPE, MOUNTED_MYTHICAL_CAPE);
|
||||
|
||||
private static final Map<Integer, PohIcons> minimapIcons;
|
||||
|
||||
@Getter
|
||||
private final String imageResource;
|
||||
@Getter
|
||||
private final int[] Ids;
|
||||
|
||||
private BufferedImage image;
|
||||
|
||||
static
|
||||
{
|
||||
ImmutableMap.Builder<Integer, PohIcons> builder = new ImmutableMap.Builder<>();
|
||||
|
||||
for (PohIcons icon : values())
|
||||
{
|
||||
for (Integer spotId : icon.getIds())
|
||||
{
|
||||
builder.put(spotId, icon);
|
||||
}
|
||||
}
|
||||
|
||||
minimapIcons = builder.build();
|
||||
}
|
||||
|
||||
PohIcons(String imageResource, int... ids)
|
||||
{
|
||||
this.imageResource = imageResource;
|
||||
this.Ids = ids;
|
||||
}
|
||||
|
||||
public static PohIcons getIcon(int id)
|
||||
{
|
||||
return minimapIcons.get(id);
|
||||
}
|
||||
|
||||
public BufferedImage getImage()
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
image = ImageUtil.getResourceStreamFromClass(getClass(), getImageResource() + ".png");
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@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.poh;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
public class PohOverlay extends Overlay
|
||||
{
|
||||
private static final PohIcons[] PORTALS = {
|
||||
PohIcons.LUMBRIDGE, PohIcons.FALADOR, PohIcons.VARROCK, PohIcons.CAMELOT, PohIcons.ARDOUGNE,
|
||||
PohIcons.YANILLE, PohIcons.LUNARISLE, PohIcons.WATERBIRTH, PohIcons.FISHINGGUILD,
|
||||
PohIcons.SENNTISTEN, PohIcons.KHARYLL, PohIcons.ANNAKARL, PohIcons.KOUREND, PohIcons.MARIM,
|
||||
PohIcons.TROLLSTRONGHOLD, PohIcons.CARRALLANGAR, PohIcons.CATHERBY, PohIcons.WEISS, PohIcons.GHORROCK,
|
||||
PohIcons.APEATOLLDUNGEON, PohIcons.BARROWS, PohIcons.BATTLEFRONT, PohIcons.CEMETERY, PohIcons.DRAYNORMANOR,
|
||||
PohIcons.FENKENSTRAINSCASTLE, PohIcons.HARMONYISLAND, PohIcons.LUMBRIDGEGRAVEYARD, PohIcons.MINDALTAR, PohIcons.SALVEGRAVEYARD,
|
||||
PohIcons.WESTARDOUGNE,
|
||||
};
|
||||
|
||||
private static final int MAX_DISTANCE = 2350;
|
||||
|
||||
@Getter
|
||||
private final List<PohIcons> iconList = new ArrayList<>();
|
||||
|
||||
private final Client client;
|
||||
private final PohConfig config;
|
||||
private final PohPlugin plugin;
|
||||
|
||||
@Inject
|
||||
public PohOverlay(Client client, PohConfig config, PohPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
LocalPoint localLocation = client.getLocalPlayer().getLocalLocation();
|
||||
plugin.getPohObjects().forEach((object, tile) ->
|
||||
{
|
||||
LocalPoint location = object.getLocalLocation();
|
||||
if (tile.getPlane() == client.getPlane() && localLocation.distanceTo(location) <= MAX_DISTANCE)
|
||||
{
|
||||
PohIcons icon = PohIcons.getIcon(object.getId());
|
||||
|
||||
if (icon != null && iconList.contains(icon))
|
||||
{
|
||||
net.runelite.api.Point minimapLoc = Perspective.getMiniMapImageLocation(client, object.getLocalLocation(), icon.getImage());
|
||||
|
||||
if (minimapLoc != null)
|
||||
{
|
||||
graphics.drawImage(icon.getImage(), minimapLoc.getX(), minimapLoc.getY(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateConfig()
|
||||
{
|
||||
iconList.clear();
|
||||
if (config.showPortals())
|
||||
{
|
||||
Collections.addAll(iconList, PORTALS);
|
||||
}
|
||||
if (config.showAltar())
|
||||
{
|
||||
iconList.add(PohIcons.ALTAR);
|
||||
}
|
||||
if (config.showGlory())
|
||||
{
|
||||
iconList.add(PohIcons.GLORY);
|
||||
}
|
||||
if (config.showRepairStand())
|
||||
{
|
||||
iconList.add(PohIcons.REPAIR);
|
||||
}
|
||||
if (config.showPools())
|
||||
{
|
||||
iconList.add(PohIcons.POOLS);
|
||||
}
|
||||
if (config.showExitPortal())
|
||||
{
|
||||
iconList.add(PohIcons.EXITPORTAL);
|
||||
}
|
||||
if (config.showSpellbook())
|
||||
{
|
||||
iconList.add(PohIcons.SPELLBOOKALTAR);
|
||||
}
|
||||
if (config.showJewelleryBox())
|
||||
{
|
||||
iconList.add(PohIcons.JEWELLERYBOX);
|
||||
}
|
||||
if (config.showMagicTravel())
|
||||
{
|
||||
iconList.add(PohIcons.MAGICTRAVEL);
|
||||
}
|
||||
if (config.showPortalNexus())
|
||||
{
|
||||
iconList.add(PohIcons.PORTALNEXUS);
|
||||
}
|
||||
if (config.showDigsitePendant())
|
||||
{
|
||||
iconList.add(PohIcons.DIGSITEPENDANT);
|
||||
}
|
||||
if (config.showXericsTalisman())
|
||||
{
|
||||
iconList.add(PohIcons.XERICSTALISMAN);
|
||||
}
|
||||
if (config.showMythicalCape())
|
||||
{
|
||||
iconList.add(PohIcons.MYTHICALCAPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@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.poh;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provides;
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.api.DecorativeObject;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.TileObject;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.DecorativeObjectDespawned;
|
||||
import net.runelite.api.events.DecorativeObjectSpawned;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.HiscoreManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||
import net.runelite.http.api.hiscore.HiscoreResult;
|
||||
import net.runelite.http.api.hiscore.Skill;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Player-owned House",
|
||||
description = "Show minimap icons and mark unlit/lit burners",
|
||||
tags = {"construction", "poh", "minimap", "overlay"}
|
||||
)
|
||||
@Slf4j
|
||||
public class PohPlugin extends Plugin
|
||||
{
|
||||
static final Set<Integer> BURNER_UNLIT = Sets.newHashSet(ObjectID.INCENSE_BURNER, ObjectID.INCENSE_BURNER_13210, ObjectID.INCENSE_BURNER_13212);
|
||||
static final Set<Integer> BURNER_LIT = Sets.newHashSet(ObjectID.INCENSE_BURNER_13209, ObjectID.INCENSE_BURNER_13211, ObjectID.INCENSE_BURNER_13213);
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Map<TileObject, Tile> pohObjects = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Map<Tile, IncenseBurner> incenseBurners = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private PohOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
@Inject
|
||||
private HiscoreManager hiscoreManager;
|
||||
|
||||
@Inject
|
||||
private BurnerOverlay burnerOverlay;
|
||||
|
||||
@Provides
|
||||
PohConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(PohConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(burnerOverlay);
|
||||
overlay.updateConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(burnerOverlay);
|
||||
pohObjects.clear();
|
||||
incenseBurners.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
overlay.updateConfig();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||
{
|
||||
final GameObject gameObject = event.getGameObject();
|
||||
|
||||
if (!BURNER_LIT.contains(gameObject.getId()) && !BURNER_UNLIT.contains(gameObject.getId()))
|
||||
{
|
||||
if (PohIcons.getIcon(gameObject.getId()) != null)
|
||||
{
|
||||
pohObjects.put(gameObject, event.getTile());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final double countdownTimer = 130.0; // Minimum amount of seconds a burner will light
|
||||
final double randomTimer = 30.0; // Minimum amount of seconds a burner will light
|
||||
incenseBurners.put(event.getTile(), new IncenseBurner(gameObject.getId(), countdownTimer, randomTimer, null));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectDespawned(GameObjectDespawned event)
|
||||
{
|
||||
GameObject gameObject = event.getGameObject();
|
||||
pohObjects.remove(gameObject);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onDecorativeObjectSpawned(DecorativeObjectSpawned event)
|
||||
{
|
||||
DecorativeObject decorativeObject = event.getDecorativeObject();
|
||||
if (PohIcons.getIcon(decorativeObject.getId()) != null)
|
||||
{
|
||||
pohObjects.put(decorativeObject, event.getTile());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onDecorativeObjectDespawned(DecorativeObjectDespawned event)
|
||||
{
|
||||
DecorativeObject decorativeObject = event.getDecorativeObject();
|
||||
pohObjects.remove(decorativeObject);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOADING)
|
||||
{
|
||||
pohObjects.clear();
|
||||
incenseBurners.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged event)
|
||||
{
|
||||
final Actor actor = event.getActor();
|
||||
final String actorName = actor.getName();
|
||||
|
||||
if (!(actor instanceof Player) || actor.getAnimation() != AnimationID.INCENSE_BURNER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final LocalPoint loc = actor.getLocalLocation();
|
||||
|
||||
// Find burner closest to player
|
||||
incenseBurners.keySet()
|
||||
.stream()
|
||||
.min(Comparator.comparingInt(a -> loc.distanceTo(a.getLocalLocation())))
|
||||
.ifPresent(tile ->
|
||||
{
|
||||
final IncenseBurner incenseBurner = incenseBurners.get(tile);
|
||||
|
||||
if (actor == client.getLocalPlayer())
|
||||
{
|
||||
int level = client.getRealSkillLevel(net.runelite.api.Skill.FIREMAKING);
|
||||
updateBurner(incenseBurner, level);
|
||||
}
|
||||
else if (actorName != null)
|
||||
{
|
||||
lookupPlayer(actorName, incenseBurner);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void lookupPlayer(String playerName, IncenseBurner incenseBurner)
|
||||
{
|
||||
executor.execute(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
final HiscoreResult playerStats = hiscoreManager.lookup(playerName, HiscoreEndpoint.NORMAL);
|
||||
|
||||
if (playerStats == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Skill fm = playerStats.getFiremaking();
|
||||
final int level = fm.getLevel();
|
||||
updateBurner(incenseBurner, Math.max(level, 1));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("Error fetching Hiscore data " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void updateBurner(IncenseBurner incenseBurner, int fmLevel)
|
||||
{
|
||||
final double tickLengthSeconds = Constants.GAME_TICK_LENGTH / 1000.0;
|
||||
incenseBurner.setCountdownTimer((200 + fmLevel) * tickLengthSeconds);
|
||||
incenseBurner.setRandomTimer(fmLevel * tickLengthSeconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Spudjb <https://github.com/spudjb>
|
||||
* 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.questlist;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.ScriptPostFired;
|
||||
import net.runelite.api.events.VarClientIntChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Quest List",
|
||||
description = "Adds searching and filtering to the quest list"
|
||||
)
|
||||
public class QuestListPlugin extends Plugin
|
||||
{
|
||||
private static final int ENTRY_PADDING = 8;
|
||||
private static final List<String> QUEST_HEADERS = ImmutableList.of("Free Quests", "Members' Quests", "Miniquests");
|
||||
|
||||
private static final String MENU_OPEN = "Open";
|
||||
private static final String MENU_CLOSE = "Close";
|
||||
|
||||
private static final String MENU_TOGGLE = "Toggle";
|
||||
|
||||
private static final String MENU_SEARCH = "Search";
|
||||
private static final String MENU_SHOW = "Show";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private ChatboxTextInput searchInput;
|
||||
private Widget questSearchButton;
|
||||
private Widget questHideButton;
|
||||
|
||||
private EnumMap<QuestContainer, Collection<QuestWidget>> questSet;
|
||||
|
||||
private QuestState currentFilterState;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
currentFilterState = QuestState.ALL;
|
||||
clientThread.invoke(this::addQuestButtons);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
currentFilterState = null;
|
||||
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||
if (header != null)
|
||||
{
|
||||
header.deleteAllChildren();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged e)
|
||||
{
|
||||
if (e.getGameState() == GameState.LOGGING_IN)
|
||||
{
|
||||
currentFilterState = QuestState.ALL;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptPostFired(ScriptPostFired event)
|
||||
{
|
||||
if (event.getScriptId() != ScriptID.QUESTLIST_PROGRESS_LIST_SHOW)
|
||||
{
|
||||
return;
|
||||
}
|
||||
addQuestButtons();
|
||||
}
|
||||
|
||||
private void addQuestButtons()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||
if (header != null)
|
||||
{
|
||||
header.deleteAllChildren();
|
||||
|
||||
questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
questSearchButton.setOriginalWidth(18);
|
||||
questSearchButton.setOriginalHeight(17);
|
||||
questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
questSearchButton.setOriginalX(5);
|
||||
questSearchButton.setOriginalY(0);
|
||||
questSearchButton.setHasListener(true);
|
||||
questSearchButton.setAction(1, MENU_OPEN);
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
questSearchButton.setName(MENU_SEARCH);
|
||||
questSearchButton.revalidate();
|
||||
|
||||
questHideButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
redrawHideButton();
|
||||
|
||||
questHideButton.setOriginalWidth(13);
|
||||
questHideButton.setOriginalHeight(13);
|
||||
questHideButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
questHideButton.setOriginalX(24);
|
||||
questHideButton.setOriginalY(2);
|
||||
questHideButton.setHasListener(true);
|
||||
questHideButton.setOnOpListener((JavaScriptCallback) e -> toggleHidden());
|
||||
questHideButton.setAction(1, MENU_TOGGLE);
|
||||
questHideButton.revalidate();
|
||||
|
||||
questSet = new EnumMap<>(QuestContainer.class);
|
||||
|
||||
updateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged varbitChanged)
|
||||
{
|
||||
if (isChatboxOpen() && !isOnQuestTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
|
||||
{
|
||||
if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
|
||||
{
|
||||
if (isChatboxOpen() && !isOnQuestTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleHidden()
|
||||
{
|
||||
QuestState[] questStates = QuestState.values();
|
||||
int nextState = (currentFilterState.ordinal() + 1) % questStates.length;
|
||||
currentFilterState = questStates[nextState];
|
||||
|
||||
redrawHideButton();
|
||||
|
||||
updateFilter();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void redrawHideButton()
|
||||
{
|
||||
questHideButton.setSpriteId(currentFilterState.getSpriteId());
|
||||
questHideButton.setName(MENU_SHOW + " " + currentFilterState.getName());
|
||||
}
|
||||
|
||||
private boolean isOnQuestTab()
|
||||
{
|
||||
return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
|
||||
}
|
||||
|
||||
private boolean isChatboxOpen()
|
||||
{
|
||||
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
|
||||
}
|
||||
|
||||
private void closeSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
chatboxPanelManager.close();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void openSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
questSearchButton.setAction(1, MENU_CLOSE);
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
|
||||
searchInput = chatboxPanelManager.openTextInput("Search quest list")
|
||||
.onChanged(s -> clientThread.invokeLater(() -> updateFilter(s)))
|
||||
.onDone(s -> false)
|
||||
.onClose(() ->
|
||||
{
|
||||
clientThread.invokeLater(() -> updateFilter(""));
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
questSearchButton.setAction(1, MENU_OPEN);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private void updateFilter()
|
||||
{
|
||||
String filter = "";
|
||||
if (isChatboxOpen())
|
||||
{
|
||||
filter = searchInput.getValue();
|
||||
}
|
||||
|
||||
updateFilter(filter);
|
||||
}
|
||||
|
||||
private void updateFilter(String filter)
|
||||
{
|
||||
filter = filter.toLowerCase();
|
||||
final Widget container = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
|
||||
|
||||
final Widget freeList = client.getWidget(QuestContainer.FREE_QUESTS.widgetInfo);
|
||||
final Widget memberList = client.getWidget(QuestContainer.MEMBER_QUESTS.widgetInfo);
|
||||
final Widget miniList = client.getWidget(QuestContainer.MINI_QUESTS.widgetInfo);
|
||||
|
||||
if (container == null || freeList == null || memberList == null || miniList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateList(QuestContainer.FREE_QUESTS, filter);
|
||||
updateList(QuestContainer.MEMBER_QUESTS, filter);
|
||||
updateList(QuestContainer.MINI_QUESTS, filter);
|
||||
|
||||
memberList.setOriginalY(freeList.getOriginalY() + freeList.getOriginalHeight() + ENTRY_PADDING);
|
||||
miniList.setOriginalY(memberList.getOriginalY() + memberList.getOriginalHeight() + ENTRY_PADDING);
|
||||
|
||||
// originalHeight is changed within updateList so revalidate all lists
|
||||
freeList.revalidate();
|
||||
memberList.revalidate();
|
||||
miniList.revalidate();
|
||||
|
||||
int y = miniList.getRelativeY() + miniList.getHeight() + 10;
|
||||
|
||||
int newHeight;
|
||||
if (container.getScrollHeight() > 0)
|
||||
{
|
||||
newHeight = (container.getScrollY() * y) / container.getScrollHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
newHeight = 0;
|
||||
}
|
||||
|
||||
container.setScrollHeight(y);
|
||||
container.revalidateScroll();
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
client.runScript(
|
||||
ScriptID.UPDATE_SCROLLBAR,
|
||||
WidgetInfo.QUESTLIST_SCROLLBAR.getId(),
|
||||
WidgetInfo.QUESTLIST_CONTAINER.getId(),
|
||||
newHeight
|
||||
));
|
||||
}
|
||||
|
||||
private void updateList(QuestContainer questContainer, String filter)
|
||||
{
|
||||
Widget list = client.getWidget(questContainer.widgetInfo);
|
||||
if (list == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<QuestWidget> quests = questSet.get(questContainer);
|
||||
|
||||
if (quests != null)
|
||||
{
|
||||
// Check to make sure the list hasn't been rebuild since we were last her
|
||||
// Do this by making sure the list's dynamic children are the same as when we last saw them
|
||||
if (quests.stream().noneMatch(w ->
|
||||
{
|
||||
Widget codeWidget = w.getQuest();
|
||||
if (codeWidget == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return list.getChild(codeWidget.getIndex()) == codeWidget;
|
||||
}))
|
||||
{
|
||||
quests = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (quests == null)
|
||||
{
|
||||
// Find all of the widgets that we care about, sorting by their Y value
|
||||
quests = Arrays.stream(list.getDynamicChildren())
|
||||
.sorted(Comparator.comparing(Widget::getRelativeY))
|
||||
.filter(w -> !QUEST_HEADERS.contains(w.getText()))
|
||||
.map(w -> new QuestWidget(w, Text.removeTags(w.getText()).toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
questSet.put(questContainer, quests);
|
||||
}
|
||||
|
||||
// offset because of header
|
||||
int y = 20;
|
||||
for (QuestWidget questInfo : quests)
|
||||
{
|
||||
Widget quest = questInfo.getQuest();
|
||||
QuestState questState = QuestState.getByColor(quest.getTextColor());
|
||||
|
||||
boolean hidden;
|
||||
if (!filter.isEmpty())
|
||||
{
|
||||
// If searching, show result regardless of filtered state
|
||||
hidden = !questInfo.getTitle().contains(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise hide if it doesn't match the filter state
|
||||
if (currentFilterState == QuestState.NOT_COMPLETED)
|
||||
{
|
||||
hidden = questState == QuestState.COMPLETE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hidden = currentFilterState != QuestState.ALL && questState != currentFilterState;
|
||||
}
|
||||
}
|
||||
|
||||
quest.setHidden(hidden);
|
||||
quest.setOriginalY(y);
|
||||
quest.revalidate();
|
||||
|
||||
if (!hidden)
|
||||
{
|
||||
y += quest.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
list.setOriginalHeight(y);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum QuestContainer
|
||||
{
|
||||
FREE_QUESTS(WidgetInfo.QUESTLIST_FREE_CONTAINER),
|
||||
MEMBER_QUESTS(WidgetInfo.QUESTLIST_MEMBERS_CONTAINER),
|
||||
MINI_QUESTS(WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER);
|
||||
|
||||
private final WidgetInfo widgetInfo;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum QuestState
|
||||
{
|
||||
NOT_STARTED(0xff0000, "Not started", SpriteID.MINIMAP_ORB_HITPOINTS),
|
||||
IN_PROGRESS(0xffff00, "In progress", SpriteID.MINIMAP_ORB_HITPOINTS_DISEASE),
|
||||
COMPLETE(0xdc10d, "Completed", SpriteID.MINIMAP_ORB_HITPOINTS_POISON),
|
||||
ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER),
|
||||
NOT_COMPLETED(0, "Not Completed", SpriteID.MINIMAP_ORB_RUN);
|
||||
|
||||
private final int color;
|
||||
private final String name;
|
||||
private final int spriteId;
|
||||
|
||||
static QuestState getByColor(int color)
|
||||
{
|
||||
for (QuestState value : values())
|
||||
{
|
||||
if (value.getColor() == color)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
private static class QuestWidget
|
||||
{
|
||||
private Widget quest;
|
||||
private String title;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Abex
|
||||
* 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.skybox;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import net.runelite.api.Client;
|
||||
|
||||
class Skybox
|
||||
{
|
||||
@FunctionalInterface
|
||||
public interface ChunkMapper
|
||||
{
|
||||
/**
|
||||
* Gets the instance template chunk data for the specified point
|
||||
*
|
||||
* @see Client#getInstanceTemplateChunks
|
||||
*/
|
||||
int getTemplateChunk(int cx, int cy, int plane);
|
||||
}
|
||||
|
||||
private static final double SQRT2 = Math.sqrt(2);
|
||||
|
||||
// How many stddev per direction we need to stay visibly continuous
|
||||
// 511/512 accuracy
|
||||
private static final double BLEND_DISTRIBUTION = 3.075;
|
||||
|
||||
// This has a worst case complexity of O((BLEND_RADUS*2)^2)
|
||||
// BLEND_RADIUS is in chunks (8 tiles)
|
||||
private static final int BLEND_RADIUS = 5;
|
||||
|
||||
// The maximum number of tiles that can be blended before becoming visibly discontinuous
|
||||
private static final int MAX_BLEND = (int) ((BLEND_RADIUS * 8) / BLEND_DISTRIBUTION);
|
||||
|
||||
private static final int PLANE_ALL = 0b1111;
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("^[ \\t]*(?<expr>" +
|
||||
"//.*$|" + // //comment
|
||||
"m[ \\t]*(?<mrx>[0-9]+)[ \\t]+(?<mry>[0-9]+)|" + // m <rx> <ry>
|
||||
"r[ \\t]*(?<rx>[0-9]+)[ \\t]+(?<ry>[0-9]+)|" + // r <rx> <ry>
|
||||
"R[ \\t]*(?<rx1>[0-9]+)[ \\t]+(?<ry1>[0-9]+)[ \\t]+(?<rx2>[0-9]+)[ \\t]+(?<ry2>[0-9]+)|" + // R <rx1> <ry1> <rx2> <ry2>
|
||||
"c[ \\t]*(?<cx>[0-9-]+)[ \\t]+(?<cy>[0-9-]+)|" + // c <cx> <cy>
|
||||
"C[ \\t]*(?<cx1>[0-9-]+)[ \\t]+(?<cy1>[0-9-]+)[ \\t]+(?<cx2>[0-9-]+)[ \\t]+(?<cy2>[0-9-]+)|" + // C <cx1> <cy1> <cx2> <cy2>
|
||||
"#[ \\t]*(?<color>[0-9a-fA-F]{6}|[0-9a-fA-F]{3})|" + // #<RRGGBB> or #<RGB>
|
||||
"p[ \\t]*(?<plane>all|0?[ \\t]*1?[ \\t]*2?[ \\t]*3?)|" + // p all or p<1><2><3><4>
|
||||
"b[ \\t]*(?<blend>[0-9]+)|" + // b <blend>
|
||||
"bounds[ \\t]+(?<bx1>[0-9]+)[ \\t]+(?<by1>[0-9]+)[ \\t]+(?<bx2>[0-9]+)[ \\t]+(?<by2>[0-9]+)" + // bounds <x0> <y0> <x1> <y1>
|
||||
")[ \\t]*");
|
||||
|
||||
private final int[] chunks;
|
||||
private final int[] planeOverrides;
|
||||
|
||||
private final int x1;
|
||||
private final int y1;
|
||||
private final int x2;
|
||||
private final int y2;
|
||||
private final int stride;
|
||||
|
||||
public Skybox(InputStream is, String filename) throws IOException
|
||||
{
|
||||
this(new InputStreamReader(is, StandardCharsets.UTF_8), filename);
|
||||
}
|
||||
|
||||
public Skybox(Reader reader, String filename) throws IOException
|
||||
{
|
||||
int[] chunks = null;
|
||||
int[] planeOverrides = new int[64];
|
||||
int planeOverrideEnd = 0;
|
||||
int x1 = 0, y1 = 0, x2 = 0, y2 = 0, stride = 0;
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
int lineNo = 1;
|
||||
int color = 0;
|
||||
int plane = PLANE_ALL;
|
||||
int rx1 = 0, ry1 = 0, rx2 = 0, ry2 = 0;
|
||||
try
|
||||
{
|
||||
Matcher m = PATTERN.matcher("");
|
||||
for (String line; (line = br.readLine()) != null; lineNo++)
|
||||
{
|
||||
m.reset(line);
|
||||
int end = 0;
|
||||
while (end < line.length())
|
||||
{
|
||||
m.region(end, line.length());
|
||||
if (!m.find())
|
||||
{
|
||||
throw new IllegalArgumentException("Unexpected: \"" + line.substring(end) + "\" (" + filename + ":" + lineNo + ")");
|
||||
}
|
||||
end = m.end();
|
||||
|
||||
String expr = m.group("expr");
|
||||
if (expr == null || expr.length() <= 0 || expr.startsWith("//"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chunks == null)
|
||||
{
|
||||
if (!expr.startsWith("bounds"))
|
||||
{
|
||||
throw new IllegalArgumentException("Expected bounds (" + filename + ":" + lineNo + ")");
|
||||
}
|
||||
x1 = Integer.parseInt(m.group("bx1")) * 8;
|
||||
y1 = Integer.parseInt(m.group("by1")) * 8;
|
||||
x2 = (Integer.parseInt(m.group("bx2")) + 1) * 8;
|
||||
y2 = (Integer.parseInt(m.group("by2")) + 1) * 8;
|
||||
stride = (x2 - x1);
|
||||
chunks = new int[stride * (y2 - y1)];
|
||||
Arrays.fill(chunks, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
char cha = expr.charAt(0);
|
||||
switch (cha)
|
||||
{
|
||||
case '#':
|
||||
String sColor = m.group("color");
|
||||
int scolor = Integer.parseInt(sColor, 16);
|
||||
int cr, cg, cb;
|
||||
if (sColor.length() == 3)
|
||||
{
|
||||
// Expand #RGB to #RRGGBB
|
||||
cr = scolor >> 8 & 0xF;
|
||||
cr |= cr << 4;
|
||||
cg = scolor >> 4 & 0xF;
|
||||
cg |= cg << 4;
|
||||
cb = scolor & 0xF;
|
||||
cb |= cb << 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
cr = scolor >> 16 & 0xFF;
|
||||
cg = scolor >> 8 & 0xFF;
|
||||
cb = scolor & 0xFF;
|
||||
}
|
||||
|
||||
// Convert to YCoCg24 because it produces less blending artifacts due
|
||||
// to mismatched skew rates
|
||||
// See: https://stackoverflow.com/questions/10566668/lossless-rgb-to-ycbcr-transformation
|
||||
byte cco = (byte) (cb - cr);
|
||||
byte tmp = (byte) (cr + (cco >> 1));
|
||||
byte ccg = (byte) (tmp - cg);
|
||||
byte cy = (byte) (cg + (ccg >> 1));
|
||||
|
||||
color = color & 0xFF000000 | (cy & 0xFF) << 16 | (cco & 0xFF) << 8 | (ccg & 0xFF);
|
||||
break;
|
||||
case 'b':
|
||||
int iblend = Integer.parseInt(m.group("blend"));
|
||||
if (iblend < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Blend must be >=0 (" + filename + ":" + lineNo + ")");
|
||||
}
|
||||
if (iblend > MAX_BLEND)
|
||||
{
|
||||
throw new IllegalArgumentException("Blend must be <= " + MAX_BLEND + " (" + filename + ":" + lineNo + ")");
|
||||
}
|
||||
color = color & 0x00FFFFFF | iblend << 24;
|
||||
break;
|
||||
case 'm':
|
||||
rx2 = rx1 = Integer.parseInt(m.group("mrx"));
|
||||
ry2 = ry1 = Integer.parseInt(m.group("mry"));
|
||||
break;
|
||||
case 'p':
|
||||
String planes = m.group("plane");
|
||||
if ("all".equals(planes))
|
||||
{
|
||||
plane = PLANE_ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
plane = 0;
|
||||
for (int i = 0; i < planes.length(); i++)
|
||||
{
|
||||
plane |= 1 << (planes.charAt(i) - '0');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (cha == 'r')
|
||||
{
|
||||
rx2 = rx1 = Integer.parseInt(m.group("rx"));
|
||||
ry2 = ry1 = Integer.parseInt(m.group("ry"));
|
||||
}
|
||||
else
|
||||
{
|
||||
rx1 = Integer.parseInt(m.group("rx1"));
|
||||
ry1 = Integer.parseInt(m.group("ry1"));
|
||||
rx2 = Integer.parseInt(m.group("rx2"));
|
||||
ry2 = Integer.parseInt(m.group("ry2"));
|
||||
}
|
||||
// fallthrough
|
||||
case 'c':
|
||||
case 'C':
|
||||
int cx1 = rx1 * 8;
|
||||
int cy1 = ry1 * 8;
|
||||
int cx2 = rx2 * 8 + 7;
|
||||
int cy2 = ry2 * 8 + 7;
|
||||
if (cha == 'c')
|
||||
{
|
||||
cx2 = cx1 = cx1 + Integer.parseInt(m.group("cx"));
|
||||
cy2 = cy1 = cy1 + Integer.parseInt(m.group("cy"));
|
||||
}
|
||||
else if (cha == 'C')
|
||||
{
|
||||
cx2 = cx1 + Integer.parseInt(m.group("cx2"));
|
||||
cy2 = cy1 + Integer.parseInt(m.group("cy2"));
|
||||
cx1 = cx1 + Integer.parseInt(m.group("cx1"));
|
||||
cy1 = cy1 + Integer.parseInt(m.group("cy1"));
|
||||
}
|
||||
|
||||
if (cx1 < x1 || cy1 < y1 || cx2 >= x2 || cy2 >= y2)
|
||||
{
|
||||
throw new IllegalArgumentException("Coordinate out of bounds (" + filename + ":" + lineNo + ")");
|
||||
}
|
||||
if (cx1 > cx2 || cy1 > cy2)
|
||||
{
|
||||
throw new IllegalArgumentException("First coord must be before second (" + filename + ":" + lineNo + ")");
|
||||
}
|
||||
|
||||
for (int y = cy1; y <= cy2; y++)
|
||||
{
|
||||
int yoffset = stride * (y - y1);
|
||||
for (int x = cx1; x <= cx2; x++)
|
||||
{
|
||||
int offset = (x - x1) + yoffset;
|
||||
|
||||
if (plane == PLANE_ALL)
|
||||
{
|
||||
chunks[offset] = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are not setting all planes in this chunk, so allocate a plane override section
|
||||
// and add a pointer to it in the normal chunk's space. We do this because most chunks
|
||||
// do not have plane-specific data
|
||||
int ocv = chunks[offset];
|
||||
int poptr;
|
||||
if ((ocv & 0x8000_0000) != 0 && ocv != -1)
|
||||
{
|
||||
// Existing plane override
|
||||
poptr = ocv & 0x7FFF_FFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
poptr = planeOverrideEnd;
|
||||
planeOverrideEnd += 4;
|
||||
if (planeOverrideEnd > planeOverrides.length)
|
||||
{
|
||||
planeOverrides = Arrays.copyOf(planeOverrides, planeOverrideEnd + 64);
|
||||
}
|
||||
chunks[offset] = poptr | 0x8000_0000;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
planeOverrides[poptr + i] = ocv;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((plane & (1 << i)) != 0)
|
||||
{
|
||||
planeOverrides[poptr + i] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
throw new IllegalArgumentException("Expected number (" + filename + ":" + lineNo + ")", ex);
|
||||
}
|
||||
if (chunks == null)
|
||||
{
|
||||
throw new IllegalArgumentException(filename + ": no data");
|
||||
}
|
||||
|
||||
this.chunks = chunks;
|
||||
this.planeOverrides = planeOverrides;
|
||||
this.stride = stride;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
}
|
||||
|
||||
private int chunkData(int cx, int cy, int plane, ChunkMapper chunkMapper)
|
||||
{
|
||||
if (chunkMapper != null)
|
||||
{
|
||||
int itp = chunkMapper.getTemplateChunk(cx, cy, plane);
|
||||
if (itp == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cy = itp >> 3 & 0x7FF;
|
||||
cx = itp >> 14 & 0x3FF;
|
||||
plane = itp >> 24 & 0x3;
|
||||
}
|
||||
|
||||
if (cx < x1)
|
||||
{
|
||||
cx = x1;
|
||||
}
|
||||
if (cx >= x2)
|
||||
{
|
||||
cx = x2 - 1;
|
||||
}
|
||||
if (cy < y1)
|
||||
{
|
||||
cy = y1;
|
||||
}
|
||||
if (cy >= y2)
|
||||
{
|
||||
cy = y2 - 1;
|
||||
}
|
||||
|
||||
int cv = chunks[(stride * (cy - y1)) + (cx - x1)];
|
||||
if (cv == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if ((cv & 0x8000_0000) != 0)
|
||||
{
|
||||
cv = planeOverrides[(cv & 0x7FFF_FFFF) | plane];
|
||||
}
|
||||
return cv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the RGB color for a specific world coordinate. Arguments are floats for sub-tile accuracy.
|
||||
*
|
||||
* @param x Sample X coordinate in tiles
|
||||
* @param y Samlpe Y coordinate in tiles
|
||||
* @param x Player X coordinate in tiles
|
||||
* @param y Player Y coordinate in tiles
|
||||
* @param chunkMapper maps chunks to their instance templates, or null if not in an instance
|
||||
*/
|
||||
public int getColorForPoint(double x, double y, int px, int py, int plane, double brightness, ChunkMapper chunkMapper)
|
||||
{
|
||||
x /= 8.d;
|
||||
y /= 8.d;
|
||||
|
||||
int centerChunkData = chunkData(px / 8, py / 8, plane, chunkMapper);
|
||||
if (centerChunkData == -1)
|
||||
{
|
||||
// No data in the center chunk?
|
||||
return 0;
|
||||
}
|
||||
|
||||
double t = 0;
|
||||
double ty = 0;
|
||||
double tco = 0;
|
||||
double tcg = 0;
|
||||
|
||||
int xmin = (int) (x - BLEND_RADIUS);
|
||||
int xmax = (int) Math.ceil(x + BLEND_RADIUS);
|
||||
int ymin = (int) (y - BLEND_RADIUS);
|
||||
int ymax = (int) Math.ceil(y + BLEND_RADIUS);
|
||||
|
||||
for (int ucx = xmin; ucx < xmax; ucx++)
|
||||
{
|
||||
for (int ucy = ymin; ucy <= ymax; ucy++)
|
||||
{
|
||||
int val = chunkData(ucx, ucy, plane, chunkMapper);
|
||||
if (val == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the blend value, add 1/8 tile to make sure we don't div/0, convert to chunks
|
||||
double sigma = ((val >>> 24) + .125) / 8.d;
|
||||
|
||||
// Calculate how far we have to be away before we can discard this value without
|
||||
// becoming visibly discontinuous
|
||||
double minDist = 1 + (sigma * BLEND_DISTRIBUTION);
|
||||
|
||||
// Try to fast-fail
|
||||
double dxl = ucx - x;
|
||||
double dxh = dxl + 1.d;
|
||||
if (dxl < -minDist || dxl > minDist)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
double dyl = ucy - y;
|
||||
double dyh = dyl + 1.d;
|
||||
if (dyl < -minDist || dyh > minDist)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate integrate a gaussian distribution in each dimension for
|
||||
// this chunk relative to the requested point
|
||||
double erfdivc = sigma * SQRT2;
|
||||
double m = (erf(dxl / erfdivc) - erf(dxh / erfdivc)) * (erf(dyl / erfdivc) - erf(dyh / erfdivc));
|
||||
|
||||
// Load our YCoCg24 values into floats
|
||||
double vy = (val >>> 16 & 0xFF) / 255.d;
|
||||
double vco = (byte) (val >>> 8) / 128.d;
|
||||
double vcg = (byte) val / 128.d;
|
||||
|
||||
// And multiply by the weight
|
||||
ty += vy * m;
|
||||
tco += vco * m;
|
||||
tcg += vcg * m;
|
||||
t += m;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to int range values, and bounds check while we are at it
|
||||
byte ay = (byte) Math.min(Math.max(Math.round(ty / t * 255.d), 0), 255);
|
||||
byte aco = (byte) Math.min(Math.max(Math.round(tco * 128.d / t), -128), 127);
|
||||
byte acg = (byte) Math.min(Math.max(Math.round(tcg * 128.d / t), -128), 127);
|
||||
|
||||
// convert back to rgb from YCoCg24
|
||||
int g = (ay - (acg >> 1)) & 0xFF;
|
||||
int tmp = (g + acg) & 0xFF;
|
||||
int r = (tmp - (aco >> 1)) & 0xFF;
|
||||
int b = (r + aco) & 0xFF;
|
||||
|
||||
// increase brightness with HSB
|
||||
float[] hsb = Color.RGBtoHSB(r, g, b, null);
|
||||
hsb[2] = (float) Math.pow(hsb[2], brightness);
|
||||
|
||||
return 0xFFFFFF & Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximation of erf 'Gauss error function' which is used to calculate
|
||||
* the cumulative distribution of a gaussian distribution.
|
||||
* This is used to simulate a large kernel gaussian blur without having
|
||||
* to sample the same chunk multiple times.
|
||||
*/
|
||||
private double erf(double x)
|
||||
{
|
||||
double ax = Math.abs(x);
|
||||
double t = 1.d / (1.d + (ax * .3275911d));
|
||||
double y = 1.d - ((((((1.061405429d * t) - 1.453152027d) * t) + 1.421413741d) * t - 0.284496736d) * t + 0.254829592d) * t * Math.exp(-ax * ax);
|
||||
return Math.copySign(y, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the skybox map to an image
|
||||
*
|
||||
* @param resolution The number of pixels per tile
|
||||
* @param line How many tiles to put a line
|
||||
* @param plane the plane (0-4) to render
|
||||
*/
|
||||
BufferedImage render(double resolution, int line, int plane, ChunkMapper chunkMapper)
|
||||
{
|
||||
int w = (int) (((x2 - x1) * 8) * resolution);
|
||||
int h = (int) (((y2 - y1) * 8) * resolution);
|
||||
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
int lineEvery = line <= 0 ? Integer.MAX_VALUE : (int) (line * resolution);
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
int color;
|
||||
if (x % lineEvery == 0 || y % lineEvery == 0)
|
||||
{
|
||||
color = 0x00FFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
double fx = (x1 * 8) + (x / resolution);
|
||||
double fy = (y1 * 8) + (y / resolution);
|
||||
color = getColorForPoint(fx, fy, (int) fx, (int) fy, plane, .8, chunkMapper);
|
||||
}
|
||||
img.setRGB(x, h - 1 - y, color | 0xFF000000);
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Abex
|
||||
* 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.skybox;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Skybox",
|
||||
description = "Draws an oldschool styled skybox",
|
||||
enabledByDefault = false,
|
||||
tags = {"sky"}
|
||||
)
|
||||
public class SkyboxPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private SkyboxPluginConfig config;
|
||||
|
||||
private Skybox skybox;
|
||||
|
||||
@Override
|
||||
public void startUp() throws IOException
|
||||
{
|
||||
skybox = new Skybox(SkyboxPlugin.class.getResourceAsStream("skybox.txt"), "skybox.txt");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
client.setSkyboxColor(0);
|
||||
skybox = null;
|
||||
}
|
||||
|
||||
@Provides
|
||||
SkyboxPluginConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(SkyboxPluginConfig.class);
|
||||
}
|
||||
|
||||
private int mapChunk(int cx, int cy, int plane)
|
||||
{
|
||||
cx -= client.getBaseX() / 8;
|
||||
cy -= client.getBaseY() / 8;
|
||||
|
||||
int[][] instanceTemplateChunks = client.getInstanceTemplateChunks()[plane];
|
||||
// Blending can access this out of bounds, so do a range check
|
||||
if (cx < 0 || cx >= instanceTemplateChunks.length || cy < 0 || cy >= instanceTemplateChunks[cx].length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return instanceTemplateChunks[cx][cy];
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onBeforeRender(BeforeRender r)
|
||||
{
|
||||
if (skybox == null || client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = client.getLocalPlayer();
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Color overrideColor = player.getWorldLocation().getY() < Constants.OVERWORLD_MAX_Y
|
||||
? config.customOverworldColor() : config.customOtherColor();
|
||||
if (overrideColor != null)
|
||||
{
|
||||
client.setSkyboxColor(overrideColor.getRGB());
|
||||
return;
|
||||
}
|
||||
|
||||
int px, py;
|
||||
if (client.getOculusOrbState() == 1)
|
||||
{
|
||||
px = client.getOculusOrbFocalPointX();
|
||||
py = client.getOculusOrbFocalPointY();
|
||||
}
|
||||
else
|
||||
{
|
||||
LocalPoint p = player.getLocalLocation();
|
||||
px = p.getX();
|
||||
py = p.getY();
|
||||
}
|
||||
|
||||
// Inverse of camera location / 2
|
||||
int spx = -((client.getCameraX() - px) >> 1);
|
||||
int spy = -((client.getCameraY() - py) >> 1);
|
||||
|
||||
int baseX = client.getBaseX();
|
||||
int baseY = client.getBaseY();
|
||||
|
||||
client.setSkyboxColor(skybox.getColorForPoint(
|
||||
baseX + ((px + spx) / 128.f),
|
||||
baseY + ((py + spy) / 128.f),
|
||||
baseX + (px / 128),
|
||||
baseY + (py / 128),
|
||||
client.getPlane(),
|
||||
client.getTextureProvider().getBrightness(),
|
||||
client.isInInstancedRegion() ? this::mapChunk : null
|
||||
));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
client.setSkyboxColor(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2019 logarrhytmic <https://github.com/logarrhythmic>
|
||||
* 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.skybox;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("skybox")
|
||||
public interface SkyboxPluginConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "customOverworldColor",
|
||||
name = "Overworld sky color",
|
||||
description = "Sets the color to use for the sky in overworld areas.",
|
||||
position = 1
|
||||
)
|
||||
Color customOverworldColor();
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "customOtherColor",
|
||||
name = "Cave sky color",
|
||||
description = "Sets the color to use for the sky in non-overworld areas.",
|
||||
position = 2
|
||||
)
|
||||
Color customOtherColor();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Henry Darnell <hjdarnel@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.wiki;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(WikiPlugin.CONFIG_GROUP_KEY)
|
||||
public interface WikiConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "leftClickSearch",
|
||||
name = "Left Click Search",
|
||||
description = "Swap left-click on the Wiki button to Search",
|
||||
position = 1
|
||||
)
|
||||
default boolean leftClickSearch()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.wiki;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCComposition;
|
||||
import net.runelite.api.ObjectComposition;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.WidgetHiddenChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetConfig;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
import net.runelite.client.util.Text;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Wiki",
|
||||
description = "Adds a Wiki button that takes you to the OSRS Wiki"
|
||||
)
|
||||
public class WikiPlugin extends Plugin
|
||||
{
|
||||
static final HttpUrl WIKI_BASE = HttpUrl.parse("https://oldschool.runescape.wiki");
|
||||
static final HttpUrl WIKI_API = WIKI_BASE.newBuilder().addPathSegments("api.php").build();
|
||||
static final String UTM_SORUCE_KEY = "utm_source";
|
||||
static final String UTM_SORUCE_VALUE = "runelite";
|
||||
|
||||
private static final String MENUOP_WIKI = "Wiki";
|
||||
|
||||
@Inject
|
||||
private WikiConfig config;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
private Provider<WikiSearchChatboxTextInput> wikiSearchChatboxTextInputProvider;
|
||||
|
||||
private Widget icon;
|
||||
|
||||
private boolean wikiSelected = false;
|
||||
|
||||
static final String CONFIG_GROUP_KEY = "wiki";
|
||||
|
||||
@Provides
|
||||
WikiConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(WikiConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
clientThread.invokeLater(this::addWidgets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
clientThread.invokeLater(this::removeWidgets);
|
||||
}
|
||||
|
||||
private void removeWidgets()
|
||||
{
|
||||
|
||||
Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS);
|
||||
if (minimapOrbs == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Widget[] children = minimapOrbs.getChildren();
|
||||
if (children == null || children.length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
children[0] = null;
|
||||
|
||||
Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER);
|
||||
if (vanilla != null)
|
||||
{
|
||||
vanilla.setHidden(false);
|
||||
}
|
||||
|
||||
onDeselect();
|
||||
client.setSpellSelected(false);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onWidgetLoaded(WidgetLoaded l)
|
||||
{
|
||||
if (l.getGroupId() == WidgetID.MINIMAP_GROUP_ID)
|
||||
{
|
||||
addWidgets();
|
||||
}
|
||||
}
|
||||
|
||||
private void addWidgets()
|
||||
{
|
||||
Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS);
|
||||
if (minimapOrbs == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER);
|
||||
if (vanilla != null)
|
||||
{
|
||||
vanilla.setHidden(true);
|
||||
}
|
||||
|
||||
icon = minimapOrbs.createChild(0, WidgetType.GRAPHIC);
|
||||
icon.setSpriteId(SpriteID.WIKI_DESELECTED);
|
||||
icon.setOriginalX(0);
|
||||
icon.setOriginalY(0);
|
||||
icon.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
icon.setYPositionMode(WidgetPositionMode.ABSOLUTE_BOTTOM);
|
||||
icon.setOriginalWidth(40);
|
||||
icon.setOriginalHeight(14);
|
||||
icon.setTargetVerb("Lookup");
|
||||
icon.setName("Wiki");
|
||||
icon.setClickMask(WidgetConfig.USE_GROUND_ITEM | WidgetConfig.USE_ITEM | WidgetConfig.USE_NPC
|
||||
| WidgetConfig.USE_OBJECT | WidgetConfig.USE_WIDGET);
|
||||
icon.setNoClickThrough(true);
|
||||
icon.setOnTargetEnterListener((JavaScriptCallback) ev ->
|
||||
{
|
||||
wikiSelected = true;
|
||||
icon.setSpriteId(SpriteID.WIKI_SELECTED);
|
||||
client.setAllWidgetsAreOpTargetable(true);
|
||||
});
|
||||
|
||||
final int searchIndex = config.leftClickSearch() ? 4 : 5;
|
||||
icon.setAction(searchIndex, "Search");
|
||||
icon.setOnOpListener((JavaScriptCallback) ev ->
|
||||
{
|
||||
if (ev.getOp() == searchIndex + 1)
|
||||
{
|
||||
openSearchInput();
|
||||
}
|
||||
});
|
||||
|
||||
// This doesn't always run because we cancel the menuop
|
||||
icon.setOnTargetLeaveListener((JavaScriptCallback) ev -> onDeselect());
|
||||
icon.revalidate();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onWidgetHiddenChanged(WidgetHiddenChanged ev)
|
||||
{
|
||||
if (ev.getWidget().getId() == WidgetInfo.MINIMAP_WIKI_BANNER.getId())
|
||||
{
|
||||
ev.getWidget().setHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals(CONFIG_GROUP_KEY))
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
removeWidgets();
|
||||
addWidgets();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void onDeselect()
|
||||
{
|
||||
client.setAllWidgetsAreOpTargetable(false);
|
||||
|
||||
wikiSelected = false;
|
||||
if (icon != null)
|
||||
{
|
||||
icon.setSpriteId(SpriteID.WIKI_DESELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onMenuOptionClicked(MenuOptionClicked ev)
|
||||
{
|
||||
optarget:
|
||||
if (wikiSelected)
|
||||
{
|
||||
onDeselect();
|
||||
client.setSpellSelected(false);
|
||||
ev.consume();
|
||||
|
||||
String type;
|
||||
int id;
|
||||
String name;
|
||||
WorldPoint location;
|
||||
|
||||
switch (ev.getMenuAction())
|
||||
{
|
||||
case RUNELITE:
|
||||
// This is a quest widget op
|
||||
break optarget;
|
||||
case CANCEL:
|
||||
return;
|
||||
case ITEM_USE_ON_WIDGET:
|
||||
case SPELL_CAST_ON_GROUND_ITEM:
|
||||
{
|
||||
type = "item";
|
||||
id = itemManager.canonicalize(ev.getId());
|
||||
name = itemManager.getItemComposition(id).getName();
|
||||
location = null;
|
||||
break;
|
||||
}
|
||||
case SPELL_CAST_ON_NPC:
|
||||
{
|
||||
type = "npc";
|
||||
NPC npc = client.getCachedNPCs()[ev.getId()];
|
||||
NPCComposition nc = npc.getTransformedComposition();
|
||||
id = nc.getId();
|
||||
name = nc.getName();
|
||||
location = npc.getWorldLocation();
|
||||
break;
|
||||
}
|
||||
case SPELL_CAST_ON_GAME_OBJECT:
|
||||
{
|
||||
type = "object";
|
||||
ObjectComposition lc = client.getObjectDefinition(ev.getId());
|
||||
if (lc.getImpostorIds() != null)
|
||||
{
|
||||
lc = lc.getImpostor();
|
||||
}
|
||||
id = lc.getId();
|
||||
name = lc.getName();
|
||||
location = WorldPoint.fromScene(client, ev.getActionParam(), ev.getWidgetId(), client.getPlane());
|
||||
break;
|
||||
}
|
||||
case SPELL_CAST_ON_WIDGET:
|
||||
Widget w = getWidget(ev.getWidgetId(), ev.getActionParam());
|
||||
|
||||
if (w.getType() == WidgetType.GRAPHIC && w.getItemId() != -1)
|
||||
{
|
||||
type = "item";
|
||||
id = itemManager.canonicalize(w.getItemId());
|
||||
name = itemManager.getItemComposition(id).getName();
|
||||
location = null;
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
default:
|
||||
log.info("Unknown menu option: {} {} {}", ev, ev.getMenuAction(), ev.getMenuAction() == MenuAction.CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
name = Text.removeTags(name);
|
||||
HttpUrl.Builder urlBuilder = WIKI_BASE.newBuilder();
|
||||
urlBuilder.addPathSegments("w/Special:Lookup")
|
||||
.addQueryParameter("type", type)
|
||||
.addQueryParameter("id", "" + id)
|
||||
.addQueryParameter("name", name)
|
||||
.addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE);
|
||||
|
||||
if (location != null)
|
||||
{
|
||||
urlBuilder.addQueryParameter("x", "" + location.getX())
|
||||
.addQueryParameter("y", "" + location.getY())
|
||||
.addQueryParameter("plane", "" + location.getPlane());
|
||||
}
|
||||
|
||||
HttpUrl url = urlBuilder.build();
|
||||
|
||||
LinkBrowser.browse(url.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.getMenuAction() == MenuAction.RUNELITE)
|
||||
{
|
||||
switch (ev.getMenuOption())
|
||||
{
|
||||
case MENUOP_WIKI:
|
||||
LinkBrowser.browse(WIKI_BASE.newBuilder()
|
||||
.addPathSegment("w")
|
||||
.addPathSegment(Text.removeTags(ev.getMenuTarget()))
|
||||
.addQueryParameter(UTM_SORUCE_KEY, UTM_SORUCE_VALUE)
|
||||
.build().toString());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void openSearchInput()
|
||||
{
|
||||
wikiSearchChatboxTextInputProvider.get()
|
||||
.build();
|
||||
}
|
||||
|
||||
private Widget getWidget(int wid, int index)
|
||||
{
|
||||
Widget w = client.getWidget(wid);
|
||||
if (index != -1)
|
||||
{
|
||||
w = w.getChild(index);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
int widgetIndex = event.getActionParam0();
|
||||
int widgetID = event.getActionParam1();
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
|
||||
if (wikiSelected && event.getType() == MenuAction.SPELL_CAST_ON_WIDGET.getId())
|
||||
{
|
||||
Widget w = getWidget(widgetID, widgetIndex);
|
||||
if (w.getType() == WidgetType.GRAPHIC && w.getItemId() != -1)
|
||||
{
|
||||
for (int ourEntry = menuEntries.length - 1;ourEntry >= 0; ourEntry--)
|
||||
{
|
||||
MenuEntry entry = menuEntries[ourEntry];
|
||||
if (entry.getType() == MenuAction.SPELL_CAST_ON_WIDGET.getId())
|
||||
{
|
||||
int id = itemManager.canonicalize(w.getItemId());
|
||||
String name = itemManager.getItemComposition(id).getName();
|
||||
entry.setTarget(JagexColors.MENU_TARGET_TAG + name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we don't support this widget
|
||||
// remove the last SPELL_CAST_ON_WIDGET; we can't blindly remove the top action because some other
|
||||
// plugin might have added something on this same event, and we probably shouldn't remove that instead
|
||||
MenuEntry[] oldEntries = menuEntries;
|
||||
menuEntries = Arrays.copyOf(menuEntries, menuEntries.length - 1);
|
||||
for (int ourEntry = oldEntries.length - 1;
|
||||
ourEntry >= 2 && oldEntries[oldEntries.length - 1].getType() != MenuAction.SPELL_CAST_ON_WIDGET.getId();
|
||||
ourEntry--)
|
||||
{
|
||||
menuEntries[ourEntry - 1] = oldEntries[ourEntry];
|
||||
}
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
}
|
||||
|
||||
if (WidgetInfo.TO_GROUP(widgetID) == WidgetInfo.SKILLS_CONTAINER.getGroupId())
|
||||
{
|
||||
Widget w = getWidget(widgetID, widgetIndex);
|
||||
if (w.getActions() == null || w.getParentId() != WidgetInfo.SKILLS_CONTAINER.getId())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String action = Stream.of(w.getActions())
|
||||
.filter(s -> s != null && !s.isEmpty())
|
||||
.findFirst().orElse(null);
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1);
|
||||
|
||||
MenuEntry menuEntry = menuEntries[menuEntries.length - 1] = new MenuEntry();
|
||||
menuEntry.setTarget(action.replace("View ", "").replace(" guide", ""));
|
||||
menuEntry.setOption(MENUOP_WIKI);
|
||||
menuEntry.setParam0(widgetIndex);
|
||||
menuEntry.setParam1(widgetID);
|
||||
menuEntry.setType(MenuAction.RUNELITE.getId());
|
||||
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.wiki;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Named;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetSizeMode;
|
||||
import net.runelite.api.widgets.WidgetTextAlignment;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
@Slf4j
|
||||
public class WikiSearchChatboxTextInput extends ChatboxTextInput
|
||||
{
|
||||
private static final int LINE_HEIGHT = 20;
|
||||
private static final int CHATBOX_HEIGHT = 120;
|
||||
private static final int MAX_NUM_PREDICTIONS = (CHATBOX_HEIGHT / LINE_HEIGHT) - 2; // 1 title, 1 edit
|
||||
|
||||
private static final int PREDICTION_DEBOUNCE_DELAY_MS = 200;
|
||||
|
||||
private final ChatboxPanelManager chatboxPanelManager;
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
private Future<?> runningRequest = null;
|
||||
private List<String> predictions = ImmutableList.of();
|
||||
|
||||
private int selectedPrediction = -1;
|
||||
private String offPrediction = null;
|
||||
|
||||
@Inject
|
||||
public WikiSearchChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread,
|
||||
ScheduledExecutorService scheduledExecutorService, @Named("developerMode") final boolean developerMode,
|
||||
OkHttpClient okHttpClient)
|
||||
{
|
||||
super(chatboxPanelManager, clientThread);
|
||||
this.chatboxPanelManager = chatboxPanelManager;
|
||||
|
||||
lines(1);
|
||||
prompt("OSRS Wiki Search");
|
||||
onDone(string ->
|
||||
{
|
||||
if (string != null && string.length() > 0)
|
||||
{
|
||||
search(string);
|
||||
}
|
||||
});
|
||||
onChanged(searchString ->
|
||||
{
|
||||
selectedPrediction = -1;
|
||||
Future<?> rr = runningRequest;
|
||||
if (rr != null)
|
||||
{
|
||||
rr.cancel(false);
|
||||
}
|
||||
if (searchString.length() <= 1)
|
||||
{
|
||||
runningRequest = null;
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
predictions = ImmutableList.of();
|
||||
update();
|
||||
});
|
||||
return;
|
||||
}
|
||||
runningRequest = scheduledExecutorService.schedule(() ->
|
||||
{
|
||||
HttpUrl url = WikiPlugin.WIKI_API.newBuilder()
|
||||
.addQueryParameter("action", "opensearch")
|
||||
.addQueryParameter("search", searchString)
|
||||
.addQueryParameter("redirects", "resolve")
|
||||
.addQueryParameter("format", "json")
|
||||
.addQueryParameter("warningsaserror", Boolean.toString(developerMode))
|
||||
.build();
|
||||
|
||||
Request req = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
okHttpClient.newCall(req).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
{
|
||||
log.warn("error searching wiki", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException
|
||||
{
|
||||
String body = response.body().string();
|
||||
try // NOPMD: UseTryWithResources
|
||||
{
|
||||
JsonArray jar = new JsonParser().parse(body).getAsJsonArray();
|
||||
List<String> apredictions = gson.fromJson(jar.get(1), new TypeToken<List<String>>()
|
||||
{
|
||||
}.getType());
|
||||
|
||||
if (apredictions.size() > MAX_NUM_PREDICTIONS)
|
||||
{
|
||||
apredictions = apredictions.subList(0, MAX_NUM_PREDICTIONS);
|
||||
}
|
||||
|
||||
final List<String> bpredictions = apredictions;
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
predictions = bpredictions;
|
||||
update();
|
||||
});
|
||||
}
|
||||
catch (JsonParseException | IllegalStateException | IndexOutOfBoundsException e)
|
||||
{
|
||||
log.warn("error parsing wiki response {}", body, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
runningRequest = null;
|
||||
}, PREDICTION_DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update()
|
||||
{
|
||||
Widget container = chatboxPanelManager.getContainerWidget();
|
||||
container.deleteAllChildren();
|
||||
|
||||
Widget promptWidget = container.createChild(-1, WidgetType.TEXT);
|
||||
promptWidget.setText(getPrompt());
|
||||
promptWidget.setTextColor(0x800000);
|
||||
promptWidget.setFontId(getFontID());
|
||||
promptWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER);
|
||||
promptWidget.setOriginalX(0);
|
||||
promptWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP);
|
||||
promptWidget.setOriginalY(5);
|
||||
promptWidget.setOriginalHeight(LINE_HEIGHT);
|
||||
promptWidget.setXTextAlignment(WidgetTextAlignment.CENTER);
|
||||
promptWidget.setYTextAlignment(WidgetTextAlignment.CENTER);
|
||||
promptWidget.setWidthMode(WidgetSizeMode.MINUS);
|
||||
promptWidget.revalidate();
|
||||
|
||||
buildEdit(0, 5 + LINE_HEIGHT, container.getWidth(), LINE_HEIGHT);
|
||||
|
||||
Widget separator = container.createChild(-1, WidgetType.LINE);
|
||||
separator.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER);
|
||||
separator.setOriginalX(0);
|
||||
separator.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP);
|
||||
separator.setOriginalY(4 + (LINE_HEIGHT * 2));
|
||||
separator.setOriginalHeight(0);
|
||||
separator.setOriginalWidth(16);
|
||||
separator.setWidthMode(WidgetSizeMode.MINUS);
|
||||
separator.revalidate();
|
||||
|
||||
for (int i = 0; i < predictions.size(); i++)
|
||||
{
|
||||
String pred = predictions.get(i);
|
||||
int y = 6 + (LINE_HEIGHT * (2 + i));
|
||||
|
||||
Widget bg = container.createChild(-1, WidgetType.RECTANGLE);
|
||||
bg.setTextColor(0x4444DD);
|
||||
bg.setFilled(true);
|
||||
bg.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER);
|
||||
bg.setOriginalX(1);
|
||||
bg.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP);
|
||||
bg.setOriginalY(y);
|
||||
bg.setOriginalHeight(LINE_HEIGHT);
|
||||
bg.setOriginalWidth(16);
|
||||
bg.setWidthMode(WidgetSizeMode.MINUS);
|
||||
bg.revalidate();
|
||||
bg.setName(JagexColors.MENU_TARGET_TAG + pred);
|
||||
bg.setAction(0, "Open");
|
||||
bg.setHasListener(true);
|
||||
bg.setOnOpListener((JavaScriptCallback) ev -> search(pred));
|
||||
|
||||
Widget text = container.createChild(-1, WidgetType.TEXT);
|
||||
text.setText(pred);
|
||||
text.setFontId(getFontID());
|
||||
text.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER);
|
||||
text.setOriginalX(0);
|
||||
text.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP);
|
||||
text.setOriginalY(y);
|
||||
text.setOriginalHeight(LINE_HEIGHT);
|
||||
text.setXTextAlignment(WidgetTextAlignment.CENTER);
|
||||
text.setYTextAlignment(WidgetTextAlignment.CENTER);
|
||||
text.setWidthMode(WidgetSizeMode.MINUS);
|
||||
text.revalidate();
|
||||
|
||||
if (i == selectedPrediction)
|
||||
{
|
||||
text.setTextColor(0xFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
bg.setOpacity(255);
|
||||
text.setTextColor(0x000000);
|
||||
bg.setOnMouseRepeatListener((JavaScriptCallback) ev -> text.setTextColor(0xFFFFFF));
|
||||
bg.setOnMouseLeaveListener((JavaScriptCallback) ev -> text.setTextColor(0x000000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent ev)
|
||||
{
|
||||
if (!chatboxPanelManager.shouldTakeInput())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev.getKeyCode())
|
||||
{
|
||||
case KeyEvent.VK_UP:
|
||||
ev.consume();
|
||||
if (selectedPrediction > -1)
|
||||
{
|
||||
selectedPrediction--;
|
||||
if (selectedPrediction == -1)
|
||||
{
|
||||
value(offPrediction);
|
||||
}
|
||||
else
|
||||
{
|
||||
value(predictions.get(selectedPrediction));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KeyEvent.VK_DOWN:
|
||||
ev.consume();
|
||||
|
||||
if (selectedPrediction == -1)
|
||||
{
|
||||
offPrediction = getValue();
|
||||
}
|
||||
|
||||
selectedPrediction++;
|
||||
if (selectedPrediction >= predictions.size())
|
||||
{
|
||||
selectedPrediction = predictions.size() - 1;
|
||||
}
|
||||
|
||||
if (selectedPrediction != -1)
|
||||
{
|
||||
value(predictions.get(selectedPrediction));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.keyPressed(ev);
|
||||
}
|
||||
}
|
||||
|
||||
private void search(String search)
|
||||
{
|
||||
LinkBrowser.browse(WikiPlugin.WIKI_BASE.newBuilder()
|
||||
.addQueryParameter("search", search)
|
||||
.addQueryParameter(WikiPlugin.UTM_SORUCE_KEY, WikiPlugin.UTM_SORUCE_VALUE)
|
||||
.build()
|
||||
.toString());
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Liam Edwards <http://github.com/Spedwards>
|
||||
* 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.worldhopper;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import net.runelite.http.api.worlds.WorldRegion;
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public enum RegionFilterMode
|
||||
{
|
||||
NONE,
|
||||
AUSTRALIA(WorldRegion.AUSTRALIA),
|
||||
GERMANY(WorldRegion.GERMANY),
|
||||
UNITED_KINGDOM(WorldRegion.UNITED_KINGDOM)
|
||||
{
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "U.K.";
|
||||
}
|
||||
},
|
||||
UNITED_STATES(WorldRegion.UNITED_STATES_OF_AMERICA)
|
||||
{
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "USA";
|
||||
}
|
||||
};
|
||||
|
||||
@Getter
|
||||
private WorldRegion region;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Shawn <http://github.com/DrRobosnarfen>
|
||||
* 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.worldhopper;
|
||||
|
||||
public enum SubscriptionFilterMode
|
||||
{
|
||||
BOTH,
|
||||
FREE,
|
||||
MEMBERS
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Lotto <https://github.com/devLotto>
|
||||
* Copyright (c) 2019, gregg1494 <https://github.com/gregg1494>
|
||||
* 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.worldhopper;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Keybind;
|
||||
|
||||
@ConfigGroup(WorldHopperConfig.GROUP)
|
||||
public interface WorldHopperConfig extends Config
|
||||
{
|
||||
String GROUP = "worldhopper";
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "previousKey",
|
||||
name = "Quick-hop previous",
|
||||
description = "When you press this key you'll hop to the previous world",
|
||||
position = 0
|
||||
)
|
||||
default Keybind previousKey()
|
||||
{
|
||||
return new Keybind(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "nextKey",
|
||||
name = "Quick-hop next",
|
||||
description = "When you press this key you'll hop to the next world",
|
||||
position = 1
|
||||
)
|
||||
default Keybind nextKey()
|
||||
{
|
||||
return new Keybind(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "quickhopOutOfDanger",
|
||||
name = "Quick-hop out of dangerous worlds",
|
||||
description = "Don't hop to a PVP/high risk world when quick-hopping",
|
||||
position = 2
|
||||
)
|
||||
default boolean quickhopOutOfDanger()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "quickHopRegionFilter",
|
||||
name = "Quick-hop region",
|
||||
description = "Limit quick-hopping to worlds of a specific region",
|
||||
position = 3
|
||||
)
|
||||
default RegionFilterMode quickHopRegionFilter()
|
||||
{
|
||||
return RegionFilterMode.NONE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showSidebar",
|
||||
name = "Show world switcher sidebar",
|
||||
description = "Show sidebar containing all worlds that mimics in-game interface",
|
||||
position = 4
|
||||
)
|
||||
default boolean showSidebar()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "ping",
|
||||
name = "Show world ping",
|
||||
description = "Shows ping to each game world",
|
||||
position = 5
|
||||
)
|
||||
default boolean ping()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMessage",
|
||||
name = "Show world hop message in chat",
|
||||
description = "Shows what world is being hopped to in the chat",
|
||||
position = 6
|
||||
)
|
||||
default boolean showWorldHopMessage()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "menuOption",
|
||||
name = "Show Hop-to menu option",
|
||||
description = "Adds Hop-to menu option to the friends list and friends chat members list",
|
||||
position = 7
|
||||
)
|
||||
default boolean menuOption()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "subscriptionFilter",
|
||||
name = "Show subscription types",
|
||||
description = "Only show free worlds, member worlds, or both types of worlds in sidebar",
|
||||
position = 8
|
||||
)
|
||||
default SubscriptionFilterMode subscriptionFilter()
|
||||
{
|
||||
return SubscriptionFilterMode.BOTH;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "displayPing",
|
||||
name = "Display current ping",
|
||||
description = "Displays ping to current game world",
|
||||
position = 9
|
||||
)
|
||||
default boolean displayPing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gregg1494 <https://github.com/gregg1494>
|
||||
* 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.worldhopper;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
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.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
class WorldHopperPingOverlay extends Overlay
|
||||
{
|
||||
private static final int Y_OFFSET = 11;
|
||||
private static final int X_OFFSET = 1;
|
||||
|
||||
private final Client client;
|
||||
private final WorldHopperPlugin worldHopperPlugin;
|
||||
private final WorldHopperConfig worldHopperConfig;
|
||||
|
||||
@Inject
|
||||
private WorldHopperPingOverlay(Client client, WorldHopperPlugin worldHopperPlugin, WorldHopperConfig worldHopperConfig)
|
||||
{
|
||||
this.client = client;
|
||||
this.worldHopperPlugin = worldHopperPlugin;
|
||||
this.worldHopperConfig = worldHopperConfig;
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!worldHopperConfig.displayPing())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final int ping = worldHopperPlugin.getCurrentPing();
|
||||
if (ping < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final String text = ping + " ms";
|
||||
final int textWidth = graphics.getFontMetrics().stringWidth(text);
|
||||
final int textHeight = graphics.getFontMetrics().getAscent() - graphics.getFontMetrics().getDescent();
|
||||
|
||||
// Adjust ping offset for logout button
|
||||
Widget logoutButton = client.getWidget(WidgetInfo.RESIZABLE_MINIMAP_LOGOUT_BUTTON);
|
||||
int xOffset = X_OFFSET;
|
||||
if (logoutButton != null && !logoutButton.isHidden())
|
||||
{
|
||||
xOffset += logoutButton.getWidth();
|
||||
}
|
||||
|
||||
final int width = (int) client.getRealDimensions().getWidth();
|
||||
final Point point = new Point(width - textWidth - xOffset, textHeight + Y_OFFSET);
|
||||
OverlayUtil.renderTextLocation(graphics, point, text, Color.YELLOW);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Lotto <https://github.com/devLotto>
|
||||
* Copyright (c) 2019, gregg1494 <https://github.com/gregg1494>
|
||||
* 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.worldhopper;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.time.Instant;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.ChatPlayer;
|
||||
import net.runelite.api.FriendsChatMember;
|
||||
import net.runelite.api.FriendsChatManager;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Friend;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.NameableContainer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.PlayerMenuOptionClicked;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WorldListLoad;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.WorldsFetch;
|
||||
import net.runelite.client.game.WorldService;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.worldhopper.ping.Ping;
|
||||
import net.runelite.client.ui.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ExecutorServiceExceptionLogger;
|
||||
import net.runelite.client.util.HotkeyListener;
|
||||
import net.runelite.client.util.Text;
|
||||
import net.runelite.client.util.WorldUtil;
|
||||
import net.runelite.http.api.worlds.World;
|
||||
import net.runelite.http.api.worlds.WorldResult;
|
||||
import net.runelite.http.api.worlds.WorldType;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "World Hopper",
|
||||
description = "Allows you to quickly hop worlds",
|
||||
tags = {"ping", "switcher"}
|
||||
)
|
||||
@Slf4j
|
||||
public class WorldHopperPlugin extends Plugin
|
||||
{
|
||||
private static final int REFRESH_THROTTLE = 60_000; // ms
|
||||
private static final int MAX_PLAYER_COUNT = 1950;
|
||||
|
||||
private static final int DISPLAY_SWITCHER_MAX_ATTEMPTS = 3;
|
||||
|
||||
private static final String HOP_TO = "Hop-to";
|
||||
private static final String KICK_OPTION = "Kick";
|
||||
private static final ImmutableList<String> BEFORE_OPTIONS = ImmutableList.of("Add friend", "Remove friend", KICK_OPTION);
|
||||
private static final ImmutableList<String> AFTER_OPTIONS = ImmutableList.of("Message");
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private ClientToolbar clientToolbar;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Inject
|
||||
private ChatMessageManager chatMessageManager;
|
||||
|
||||
@Inject
|
||||
private WorldHopperConfig config;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private WorldHopperPingOverlay worldHopperOverlay;
|
||||
|
||||
@Inject
|
||||
private WorldService worldService;
|
||||
|
||||
private ScheduledExecutorService hopperExecutorService;
|
||||
|
||||
private NavigationButton navButton;
|
||||
private WorldSwitcherPanel panel;
|
||||
|
||||
private net.runelite.api.World quickHopTargetWorld;
|
||||
private int displaySwitcherAttempts = 0;
|
||||
|
||||
@Getter
|
||||
private int lastWorld;
|
||||
|
||||
private int favoriteWorld1, favoriteWorld2;
|
||||
|
||||
private ScheduledFuture<?> pingFuture, currPingFuture;
|
||||
private int currentWorld;
|
||||
private Instant lastFetch;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int currentPing;
|
||||
|
||||
private final Map<Integer, Integer> storedPings = new HashMap<>();
|
||||
|
||||
private final HotkeyListener previousKeyListener = new HotkeyListener(() -> config.previousKey())
|
||||
{
|
||||
@Override
|
||||
public void hotkeyPressed()
|
||||
{
|
||||
hop(true);
|
||||
}
|
||||
};
|
||||
private final HotkeyListener nextKeyListener = new HotkeyListener(() -> config.nextKey())
|
||||
{
|
||||
@Override
|
||||
public void hotkeyPressed()
|
||||
{
|
||||
hop(false);
|
||||
}
|
||||
};
|
||||
|
||||
@Provides
|
||||
WorldHopperConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(WorldHopperConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
currentPing = -1;
|
||||
|
||||
keyManager.registerKeyListener(previousKeyListener);
|
||||
keyManager.registerKeyListener(nextKeyListener);
|
||||
|
||||
panel = new WorldSwitcherPanel(this);
|
||||
|
||||
final BufferedImage icon;
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("icon.png"));
|
||||
}
|
||||
|
||||
navButton = NavigationButton.builder()
|
||||
.tooltip("World Switcher")
|
||||
.icon(icon)
|
||||
.priority(3)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
if (config.showSidebar())
|
||||
{
|
||||
clientToolbar.addNavigation(navButton);
|
||||
}
|
||||
|
||||
overlayManager.add(worldHopperOverlay);
|
||||
|
||||
panel.setFilterMode(config.subscriptionFilter());
|
||||
|
||||
// The plugin has its own executor for pings, as it blocks for a long time
|
||||
hopperExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor());
|
||||
// Run the first-run ping
|
||||
hopperExecutorService.execute(this::pingInitialWorlds);
|
||||
|
||||
// Give some initial delay - this won't run until after pingInitialWorlds finishes from tick() anyway
|
||||
pingFuture = hopperExecutorService.scheduleWithFixedDelay(this::pingNextWorld, 15, 3, TimeUnit.SECONDS);
|
||||
currPingFuture = hopperExecutorService.scheduleWithFixedDelay(this::pingCurrentWorld, 15, 1, TimeUnit.SECONDS);
|
||||
|
||||
// populate initial world list
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
pingFuture.cancel(true);
|
||||
pingFuture = null;
|
||||
|
||||
currPingFuture.cancel(true);
|
||||
currPingFuture = null;
|
||||
|
||||
overlayManager.remove(worldHopperOverlay);
|
||||
|
||||
keyManager.unregisterKeyListener(previousKeyListener);
|
||||
keyManager.unregisterKeyListener(nextKeyListener);
|
||||
|
||||
clientToolbar.removeNavigation(navButton);
|
||||
|
||||
hopperExecutorService.shutdown();
|
||||
hopperExecutorService = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(final ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals(WorldHopperConfig.GROUP))
|
||||
{
|
||||
switch (event.getKey())
|
||||
{
|
||||
case "showSidebar":
|
||||
if (config.showSidebar())
|
||||
{
|
||||
clientToolbar.addNavigation(navButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientToolbar.removeNavigation(navButton);
|
||||
}
|
||||
break;
|
||||
case "ping":
|
||||
if (config.ping())
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> panel.showPing());
|
||||
}
|
||||
else
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> panel.hidePing());
|
||||
}
|
||||
break;
|
||||
case "subscriptionFilter":
|
||||
panel.setFilterMode(config.subscriptionFilter());
|
||||
updateList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setFavoriteConfig(int world)
|
||||
{
|
||||
configManager.setConfiguration(WorldHopperConfig.GROUP, "favorite_" + world, true);
|
||||
}
|
||||
|
||||
private boolean isFavoriteConfig(int world)
|
||||
{
|
||||
Boolean favorite = configManager.getConfiguration(WorldHopperConfig.GROUP, "favorite_" + world, Boolean.class);
|
||||
return favorite != null && favorite;
|
||||
}
|
||||
|
||||
private void clearFavoriteConfig(int world)
|
||||
{
|
||||
configManager.unsetConfiguration(WorldHopperConfig.GROUP, "favorite_" + world);
|
||||
}
|
||||
|
||||
boolean isFavorite(World world)
|
||||
{
|
||||
int id = world.getId();
|
||||
return id == favoriteWorld1 || id == favoriteWorld2 || isFavoriteConfig(id);
|
||||
}
|
||||
|
||||
int getCurrentWorld()
|
||||
{
|
||||
return client.getWorld();
|
||||
}
|
||||
|
||||
void hopTo(World world)
|
||||
{
|
||||
hop(world.getId());
|
||||
}
|
||||
|
||||
void addToFavorites(World world)
|
||||
{
|
||||
log.debug("Adding world {} to favorites", world.getId());
|
||||
setFavoriteConfig(world.getId());
|
||||
panel.updateFavoriteMenu(world.getId(), true);
|
||||
}
|
||||
|
||||
void removeFromFavorites(World world)
|
||||
{
|
||||
log.debug("Removing world {} from favorites", world.getId());
|
||||
clearFavoriteConfig(world.getId());
|
||||
panel.updateFavoriteMenu(world.getId(), false);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged varbitChanged)
|
||||
{
|
||||
int old1 = favoriteWorld1;
|
||||
int old2 = favoriteWorld2;
|
||||
|
||||
favoriteWorld1 = client.getVar(Varbits.WORLDHOPPER_FAVROITE_1);
|
||||
favoriteWorld2 = client.getVar(Varbits.WORLDHOPPER_FAVROITE_2);
|
||||
|
||||
if (old1 != favoriteWorld1 || old2 != favoriteWorld2)
|
||||
{
|
||||
SwingUtilities.invokeLater(panel::updateList);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (!config.menuOption())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int groupId = WidgetInfo.TO_GROUP(event.getActionParam1());
|
||||
String option = event.getOption();
|
||||
|
||||
if (groupId == WidgetInfo.FRIENDS_LIST.getGroupId() || groupId == WidgetInfo.FRIENDS_CHAT.getGroupId())
|
||||
{
|
||||
boolean after;
|
||||
|
||||
if (AFTER_OPTIONS.contains(option))
|
||||
{
|
||||
after = true;
|
||||
}
|
||||
else if (BEFORE_OPTIONS.contains(option))
|
||||
{
|
||||
after = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't add entry if user is offline
|
||||
ChatPlayer player = getChatPlayerFromName(event.getTarget());
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
|
||||
if (player == null || player.getWorld() == 0 || player.getWorld() == client.getWorld()
|
||||
|| worldResult == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
World currentWorld = worldResult.findWorld(client.getWorld());
|
||||
World targetWorld = worldResult.findWorld(player.getWorld());
|
||||
if (targetWorld == null || currentWorld == null
|
||||
|| (!currentWorld.getTypes().contains(WorldType.PVP) && targetWorld.getTypes().contains(WorldType.PVP)))
|
||||
{
|
||||
// Disable Hop-to a PVP world from a regular world
|
||||
return;
|
||||
}
|
||||
|
||||
final MenuEntry hopTo = new MenuEntry();
|
||||
hopTo.setOption(HOP_TO);
|
||||
hopTo.setTarget(event.getTarget());
|
||||
hopTo.setType(MenuAction.RUNELITE.getId());
|
||||
hopTo.setParam0(event.getActionParam0());
|
||||
hopTo.setParam1(event.getActionParam1());
|
||||
|
||||
insertMenuEntry(hopTo, client.getMenuEntries(), after);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertMenuEntry(MenuEntry newEntry, MenuEntry[] entries, boolean after)
|
||||
{
|
||||
MenuEntry[] newMenu = ObjectArrays.concat(entries, newEntry);
|
||||
|
||||
if (after)
|
||||
{
|
||||
int menuEntryCount = newMenu.length;
|
||||
ArrayUtils.swap(newMenu, menuEntryCount - 1, menuEntryCount - 2);
|
||||
}
|
||||
|
||||
client.setMenuEntries(newMenu);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event)
|
||||
{
|
||||
if (!event.getMenuOption().equals(HOP_TO))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ChatPlayer player = getChatPlayerFromName(event.getMenuTarget());
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
hop(player.getWorld());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
// If the player has disabled the side bar plugin panel, do not update the UI
|
||||
if (config.showSidebar() && gameStateChanged.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
if (lastWorld != client.getWorld())
|
||||
{
|
||||
int newWorld = client.getWorld();
|
||||
panel.switchCurrentHighlight(newWorld, lastWorld);
|
||||
lastWorld = newWorld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWorldListLoad(WorldListLoad worldListLoad)
|
||||
{
|
||||
if (!config.showSidebar())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Integer, Integer> worldData = new HashMap<>();
|
||||
|
||||
for (net.runelite.api.World w : worldListLoad.getWorlds())
|
||||
{
|
||||
worldData.put(w.getId(), w.getPlayerCount());
|
||||
}
|
||||
|
||||
panel.updateListData(worldData);
|
||||
this.lastFetch = Instant.now(); // This counts as a fetch as it updates populations
|
||||
}
|
||||
|
||||
void refresh()
|
||||
{
|
||||
Instant now = Instant.now();
|
||||
if (lastFetch != null && now.toEpochMilli() - lastFetch.toEpochMilli() < REFRESH_THROTTLE)
|
||||
{
|
||||
log.debug("Throttling world refresh");
|
||||
return;
|
||||
}
|
||||
|
||||
lastFetch = now;
|
||||
worldService.refresh();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWorldsFetch(WorldsFetch worldsFetch)
|
||||
{
|
||||
updateList();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method ONLY updates the list's UI, not the actual world list and data it displays.
|
||||
*/
|
||||
private void updateList()
|
||||
{
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
if (worldResult != null)
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> panel.populate(worldResult.getWorlds()));
|
||||
}
|
||||
}
|
||||
|
||||
private void hop(boolean previous)
|
||||
{
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
if (worldResult == null || client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
World currentWorld = worldResult.findWorld(client.getWorld());
|
||||
|
||||
if (currentWorld == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnumSet<WorldType> currentWorldTypes = currentWorld.getTypes().clone();
|
||||
// Make it so you always hop out of PVP and high risk worlds
|
||||
if (config.quickhopOutOfDanger())
|
||||
{
|
||||
currentWorldTypes.remove(WorldType.PVP);
|
||||
currentWorldTypes.remove(WorldType.HIGH_RISK);
|
||||
}
|
||||
// Don't regard these worlds as a type that must be hopped between
|
||||
currentWorldTypes.remove(WorldType.BOUNTY);
|
||||
currentWorldTypes.remove(WorldType.SKILL_TOTAL);
|
||||
currentWorldTypes.remove(WorldType.LAST_MAN_STANDING);
|
||||
|
||||
List<World> worlds = worldResult.getWorlds();
|
||||
|
||||
int worldIdx = worlds.indexOf(currentWorld);
|
||||
int totalLevel = client.getTotalLevel();
|
||||
|
||||
World world;
|
||||
do
|
||||
{
|
||||
/*
|
||||
Get the previous or next world in the list,
|
||||
starting over at the other end of the list
|
||||
if there are no more elements in the
|
||||
current direction of iteration.
|
||||
*/
|
||||
if (previous)
|
||||
{
|
||||
worldIdx--;
|
||||
|
||||
if (worldIdx < 0)
|
||||
{
|
||||
worldIdx = worlds.size() - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
worldIdx++;
|
||||
|
||||
if (worldIdx >= worlds.size())
|
||||
{
|
||||
worldIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
world = worlds.get(worldIdx);
|
||||
|
||||
// Check world region if filter is enabled
|
||||
if (config.quickHopRegionFilter() != RegionFilterMode.NONE && world.getRegion() != config.quickHopRegionFilter().getRegion())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
EnumSet<WorldType> types = world.getTypes().clone();
|
||||
|
||||
types.remove(WorldType.BOUNTY);
|
||||
// Treat LMS world like casual world
|
||||
types.remove(WorldType.LAST_MAN_STANDING);
|
||||
|
||||
if (types.contains(WorldType.SKILL_TOTAL))
|
||||
{
|
||||
try
|
||||
{
|
||||
int totalRequirement = Integer.parseInt(world.getActivity().substring(0, world.getActivity().indexOf(" ")));
|
||||
|
||||
if (totalLevel >= totalRequirement)
|
||||
{
|
||||
types.remove(WorldType.SKILL_TOTAL);
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
log.warn("Failed to parse total level requirement for target world", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid switching to near-max population worlds, as it will refuse to allow the hop if the world is full
|
||||
if (world.getPlayers() >= MAX_PLAYER_COUNT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Break out if we've found a good world to hop to
|
||||
if (currentWorldTypes.equals(types))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (world != currentWorld);
|
||||
|
||||
if (world == currentWorld)
|
||||
{
|
||||
String chatMessage = new ChatMessageBuilder()
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append("Couldn't find a world to quick-hop to.")
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(chatMessage)
|
||||
.build());
|
||||
}
|
||||
else
|
||||
{
|
||||
hop(world.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void hop(int worldId)
|
||||
{
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
// Don't try to hop if the world doesn't exist
|
||||
World world = worldResult.findWorld(worldId);
|
||||
if (world == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final net.runelite.api.World rsWorld = client.createWorld();
|
||||
rsWorld.setActivity(world.getActivity());
|
||||
rsWorld.setAddress(world.getAddress());
|
||||
rsWorld.setId(world.getId());
|
||||
rsWorld.setPlayerCount(world.getPlayers());
|
||||
rsWorld.setLocation(world.getLocation());
|
||||
rsWorld.setTypes(WorldUtil.toWorldTypes(world.getTypes()));
|
||||
|
||||
if (client.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
// on the login screen we can just change the world by ourselves
|
||||
client.changeWorld(rsWorld);
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.showWorldHopMessage())
|
||||
{
|
||||
String chatMessage = new ChatMessageBuilder()
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append("Quick-hopping to World ")
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append(Integer.toString(world.getId()))
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append("..")
|
||||
.build();
|
||||
|
||||
chatMessageManager
|
||||
.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(chatMessage)
|
||||
.build());
|
||||
}
|
||||
|
||||
quickHopTargetWorld = rsWorld;
|
||||
displaySwitcherAttempts = 0;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
if (quickHopTargetWorld == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.getWidget(WidgetInfo.WORLD_SWITCHER_LIST) == null)
|
||||
{
|
||||
client.openWorldHopper();
|
||||
|
||||
if (++displaySwitcherAttempts >= DISPLAY_SWITCHER_MAX_ATTEMPTS)
|
||||
{
|
||||
String chatMessage = new ChatMessageBuilder()
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append("Failed to quick-hop after ")
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append(Integer.toString(displaySwitcherAttempts))
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append(" attempts.")
|
||||
.build();
|
||||
|
||||
chatMessageManager
|
||||
.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(chatMessage)
|
||||
.build());
|
||||
|
||||
resetQuickHopper();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client.hopToWorld(quickHopTargetWorld);
|
||||
resetQuickHopper();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (event.getType() != ChatMessageType.GAMEMESSAGE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getMessage().equals("Please finish what you're doing before using the World Switcher."))
|
||||
{
|
||||
resetQuickHopper();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetQuickHopper()
|
||||
{
|
||||
displaySwitcherAttempts = 0;
|
||||
quickHopTargetWorld = null;
|
||||
}
|
||||
|
||||
private ChatPlayer getChatPlayerFromName(String name)
|
||||
{
|
||||
String cleanName = Text.removeTags(name);
|
||||
|
||||
// Search friends chat members first, because we can always get their world;
|
||||
// friends worlds may be hidden if they have private off. (#5679)
|
||||
FriendsChatManager friendsChatManager = client.getFriendsChatManager();
|
||||
if (friendsChatManager != null)
|
||||
{
|
||||
FriendsChatMember member = friendsChatManager.findByName(cleanName);
|
||||
if (member != null)
|
||||
{
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
NameableContainer<Friend> friendContainer = client.getFriendContainer();
|
||||
if (friendContainer != null)
|
||||
{
|
||||
return friendContainer.findByName(cleanName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping all worlds. This takes a long time and is only run on first run.
|
||||
*/
|
||||
private void pingInitialWorlds()
|
||||
{
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
if (worldResult == null || !config.showSidebar() || !config.ping())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
for (World world : worldResult.getWorlds())
|
||||
{
|
||||
int ping = ping(world);
|
||||
SwingUtilities.invokeLater(() -> panel.updatePing(world.getId(), ping));
|
||||
}
|
||||
|
||||
stopwatch.stop();
|
||||
|
||||
log.debug("Done pinging worlds in {}", stopwatch.elapsed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the next world
|
||||
*/
|
||||
private void pingNextWorld()
|
||||
{
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
if (worldResult == null || !config.showSidebar() || !config.ping())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<World> worlds = worldResult.getWorlds();
|
||||
if (worlds.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentWorld >= worlds.size())
|
||||
{
|
||||
// Wrap back around
|
||||
currentWorld = 0;
|
||||
}
|
||||
|
||||
World world = worlds.get(currentWorld++);
|
||||
|
||||
// If we are displaying the ping overlay, there is a separate scheduled task for the current world
|
||||
boolean displayPing = config.displayPing() && client.getGameState() == GameState.LOGGED_IN;
|
||||
if (displayPing && client.getWorld() == world.getId())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int ping = ping(world);
|
||||
log.trace("Ping for world {} is: {}", world.getId(), ping);
|
||||
SwingUtilities.invokeLater(() -> panel.updatePing(world.getId(), ping));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the current world for the ping overlay
|
||||
*/
|
||||
private void pingCurrentWorld()
|
||||
{
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
// There is no reason to ping the current world if not logged in, as the overlay doesn't draw
|
||||
if (worldResult == null || !config.displayPing() || client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final World currentWorld = worldResult.findWorld(client.getWorld());
|
||||
if (currentWorld == null)
|
||||
{
|
||||
log.debug("unable to find current world: {}", client.getWorld());
|
||||
return;
|
||||
}
|
||||
|
||||
currentPing = ping(currentWorld);
|
||||
log.trace("Ping for current world is: {}", currentPing);
|
||||
|
||||
SwingUtilities.invokeLater(() -> panel.updatePing(currentWorld.getId(), currentPing));
|
||||
}
|
||||
|
||||
Integer getStoredPing(World world)
|
||||
{
|
||||
if (!config.ping())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return storedPings.get(world.getId());
|
||||
}
|
||||
|
||||
private int ping(World world)
|
||||
{
|
||||
int ping = Ping.ping(world);
|
||||
storedPings.put(world.getId(), ping);
|
||||
return ping;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Psikoi <https://github.com/Psikoi>
|
||||
* 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.worldhopper;
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Setter;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.DynamicGridLayout;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import net.runelite.http.api.worlds.World;
|
||||
import net.runelite.http.api.worlds.WorldType;
|
||||
|
||||
class WorldSwitcherPanel extends PluginPanel
|
||||
{
|
||||
private static final Color ODD_ROW = new Color(44, 44, 44);
|
||||
|
||||
private static final int WORLD_COLUMN_WIDTH = 60;
|
||||
private static final int PLAYERS_COLUMN_WIDTH = 40;
|
||||
private static final int PING_COLUMN_WIDTH = 47;
|
||||
|
||||
private final JPanel listContainer = new JPanel();
|
||||
|
||||
private WorldTableHeader worldHeader;
|
||||
private WorldTableHeader playersHeader;
|
||||
private WorldTableHeader activityHeader;
|
||||
private WorldTableHeader pingHeader;
|
||||
|
||||
private WorldOrder orderIndex = WorldOrder.WORLD;
|
||||
private boolean ascendingOrder = true;
|
||||
|
||||
private final ArrayList<WorldTableRow> rows = new ArrayList<>();
|
||||
private final WorldHopperPlugin plugin;
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private SubscriptionFilterMode filterMode;
|
||||
|
||||
WorldSwitcherPanel(WorldHopperPlugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
|
||||
setBorder(null);
|
||||
setLayout(new DynamicGridLayout(0, 1));
|
||||
|
||||
JPanel headerContainer = buildHeader();
|
||||
|
||||
listContainer.setLayout(new GridLayout(0, 1));
|
||||
|
||||
add(headerContainer);
|
||||
add(listContainer);
|
||||
}
|
||||
|
||||
void switchCurrentHighlight(int newWorld, int lastWorld)
|
||||
{
|
||||
for (WorldTableRow row : rows)
|
||||
{
|
||||
if (row.getWorld().getId() == newWorld)
|
||||
{
|
||||
row.recolour(true);
|
||||
}
|
||||
else if (row.getWorld().getId() == lastWorld)
|
||||
{
|
||||
row.recolour(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateListData(Map<Integer, Integer> worldData)
|
||||
{
|
||||
for (WorldTableRow worldTableRow : rows)
|
||||
{
|
||||
World world = worldTableRow.getWorld();
|
||||
Integer playerCount = worldData.get(world.getId());
|
||||
if (playerCount != null)
|
||||
{
|
||||
worldTableRow.updatePlayerCount(playerCount);
|
||||
}
|
||||
}
|
||||
|
||||
// If the list is being ordered by player count, then it has to be re-painted
|
||||
// to properly display the new data
|
||||
if (orderIndex == WorldOrder.PLAYERS)
|
||||
{
|
||||
updateList();
|
||||
}
|
||||
}
|
||||
|
||||
void updatePing(int world, int ping)
|
||||
{
|
||||
for (WorldTableRow worldTableRow : rows)
|
||||
{
|
||||
if (worldTableRow.getWorld().getId() == world)
|
||||
{
|
||||
worldTableRow.setPing(ping);
|
||||
|
||||
// If the panel is sorted by ping, re-sort it
|
||||
if (orderIndex == WorldOrder.PING)
|
||||
{
|
||||
updateList();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hidePing()
|
||||
{
|
||||
for (WorldTableRow worldTableRow : rows)
|
||||
{
|
||||
worldTableRow.hidePing();
|
||||
}
|
||||
}
|
||||
|
||||
void showPing()
|
||||
{
|
||||
for (WorldTableRow worldTableRow : rows)
|
||||
{
|
||||
worldTableRow.showPing();
|
||||
}
|
||||
}
|
||||
|
||||
void updateList()
|
||||
{
|
||||
rows.sort((r1, r2) ->
|
||||
{
|
||||
switch (orderIndex)
|
||||
{
|
||||
case PING:
|
||||
// Leave worlds with unknown ping at the bottom
|
||||
return getCompareValue(r1, r2, row ->
|
||||
{
|
||||
int ping = row.getPing();
|
||||
return ping > 0 ? ping : null;
|
||||
});
|
||||
case WORLD:
|
||||
return getCompareValue(r1, r2, row -> row.getWorld().getId());
|
||||
case PLAYERS:
|
||||
return getCompareValue(r1, r2, WorldTableRow::getUpdatedPlayerCount);
|
||||
case ACTIVITY:
|
||||
// Leave empty activity worlds on the bottom of the list
|
||||
return getCompareValue(r1, r2, row ->
|
||||
{
|
||||
String activity = row.getWorld().getActivity();
|
||||
return !activity.equals("-") ? activity : null;
|
||||
});
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
rows.sort((r1, r2) ->
|
||||
{
|
||||
boolean b1 = plugin.isFavorite(r1.getWorld());
|
||||
boolean b2 = plugin.isFavorite(r2.getWorld());
|
||||
return Boolean.compare(b2, b1);
|
||||
});
|
||||
|
||||
listContainer.removeAll();
|
||||
|
||||
for (int i = 0; i < rows.size(); i++)
|
||||
{
|
||||
WorldTableRow row = rows.get(i);
|
||||
row.setBackground(i % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR);
|
||||
listContainer.add(row);
|
||||
}
|
||||
|
||||
listContainer.revalidate();
|
||||
listContainer.repaint();
|
||||
}
|
||||
|
||||
private int getCompareValue(WorldTableRow row1, WorldTableRow row2, Function<WorldTableRow, Comparable> compareByFn)
|
||||
{
|
||||
Ordering<Comparable> ordering = Ordering.natural();
|
||||
if (!ascendingOrder)
|
||||
{
|
||||
ordering = ordering.reverse();
|
||||
}
|
||||
ordering = ordering.nullsLast();
|
||||
return ordering.compare(compareByFn.apply(row1), compareByFn.apply(row2));
|
||||
}
|
||||
|
||||
void updateFavoriteMenu(int world, boolean favorite)
|
||||
{
|
||||
for (WorldTableRow row : rows)
|
||||
{
|
||||
if (row.getWorld().getId() == world)
|
||||
{
|
||||
row.setFavoriteMenu(favorite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void populate(List<World> worlds)
|
||||
{
|
||||
rows.clear();
|
||||
|
||||
for (int i = 0; i < worlds.size(); i++)
|
||||
{
|
||||
World world = worlds.get(i);
|
||||
|
||||
switch (filterMode)
|
||||
{
|
||||
case FREE:
|
||||
if (world.getTypes().contains(WorldType.MEMBERS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case MEMBERS:
|
||||
if (!world.getTypes().contains(WorldType.MEMBERS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world)));
|
||||
}
|
||||
|
||||
updateList();
|
||||
}
|
||||
|
||||
private void orderBy(WorldOrder order)
|
||||
{
|
||||
pingHeader.highlight(false, ascendingOrder);
|
||||
worldHeader.highlight(false, ascendingOrder);
|
||||
playersHeader.highlight(false, ascendingOrder);
|
||||
activityHeader.highlight(false, ascendingOrder);
|
||||
|
||||
switch (order)
|
||||
{
|
||||
case PING:
|
||||
pingHeader.highlight(true, ascendingOrder);
|
||||
break;
|
||||
case WORLD:
|
||||
worldHeader.highlight(true, ascendingOrder);
|
||||
break;
|
||||
case PLAYERS:
|
||||
playersHeader.highlight(true, ascendingOrder);
|
||||
break;
|
||||
case ACTIVITY:
|
||||
activityHeader.highlight(true, ascendingOrder);
|
||||
break;
|
||||
}
|
||||
|
||||
orderIndex = order;
|
||||
updateList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the entire table header.
|
||||
*/
|
||||
private JPanel buildHeader()
|
||||
{
|
||||
JPanel header = new JPanel(new BorderLayout());
|
||||
JPanel leftSide = new JPanel(new BorderLayout());
|
||||
JPanel rightSide = new JPanel(new BorderLayout());
|
||||
|
||||
pingHeader = new WorldTableHeader("Ping", orderIndex == WorldOrder.PING, ascendingOrder, plugin::refresh);
|
||||
pingHeader.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0));
|
||||
pingHeader.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ascendingOrder = orderIndex != WorldOrder.PING || !ascendingOrder;
|
||||
orderBy(WorldOrder.PING);
|
||||
}
|
||||
});
|
||||
|
||||
worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder, plugin::refresh);
|
||||
worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0));
|
||||
worldHeader.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder;
|
||||
orderBy(WorldOrder.WORLD);
|
||||
}
|
||||
});
|
||||
|
||||
playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder, plugin::refresh);
|
||||
playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0));
|
||||
playersHeader.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder;
|
||||
orderBy(WorldOrder.PLAYERS);
|
||||
}
|
||||
});
|
||||
|
||||
activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder, plugin::refresh);
|
||||
activityHeader.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder;
|
||||
orderBy(WorldOrder.ACTIVITY);
|
||||
}
|
||||
});
|
||||
|
||||
leftSide.add(worldHeader, BorderLayout.WEST);
|
||||
leftSide.add(playersHeader, BorderLayout.CENTER);
|
||||
|
||||
rightSide.add(activityHeader, BorderLayout.CENTER);
|
||||
rightSide.add(pingHeader, BorderLayout.EAST);
|
||||
|
||||
header.add(leftSide, BorderLayout.WEST);
|
||||
header.add(rightSide, BorderLayout.CENTER);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a table row, that displays the world's information.
|
||||
*/
|
||||
private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite)
|
||||
{
|
||||
WorldTableRow row = new WorldTableRow(world, current, favorite, plugin.getStoredPing(world),
|
||||
world1 ->
|
||||
{
|
||||
plugin.hopTo(world1);
|
||||
},
|
||||
(world12, add) ->
|
||||
{
|
||||
if (add)
|
||||
{
|
||||
plugin.addToFavorites(world12);
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin.removeFromFavorites(world12);
|
||||
}
|
||||
|
||||
updateList();
|
||||
}
|
||||
);
|
||||
row.setBackground(stripe ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR);
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates the multiple ordering options for the world list.
|
||||
*/
|
||||
private enum WorldOrder
|
||||
{
|
||||
WORLD,
|
||||
PLAYERS,
|
||||
ACTIVITY,
|
||||
PING
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Psikoi <https://github.com/Psikoi>
|
||||
* 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.worldhopper;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
class WorldTableHeader extends JPanel
|
||||
{
|
||||
private static final ImageIcon ARROW_UP;
|
||||
private static final ImageIcon HIGHLIGHT_ARROW_DOWN;
|
||||
private static final ImageIcon HIGHLIGHT_ARROW_UP;
|
||||
|
||||
private static final Color ARROW_COLOR = ColorScheme.LIGHT_GRAY_COLOR;
|
||||
private static final Color HIGHLIGHT_COLOR = ColorScheme.BRAND_ORANGE;
|
||||
|
||||
static
|
||||
{
|
||||
final BufferedImage arrowDown = ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "arrow_down.png");
|
||||
final BufferedImage arrowUp = ImageUtil.rotateImage(arrowDown, Math.PI);
|
||||
final BufferedImage arrowUpFaded = ImageUtil.luminanceOffset(arrowUp, -80);
|
||||
ARROW_UP = new ImageIcon(arrowUpFaded);
|
||||
|
||||
final BufferedImage highlightArrowDown = ImageUtil.fillImage(arrowDown, HIGHLIGHT_COLOR);
|
||||
final BufferedImage highlightArrowUp = ImageUtil.fillImage(arrowUp, HIGHLIGHT_COLOR);
|
||||
HIGHLIGHT_ARROW_DOWN = new ImageIcon(highlightArrowDown);
|
||||
HIGHLIGHT_ARROW_UP = new ImageIcon(highlightArrowUp);
|
||||
}
|
||||
|
||||
private final JLabel textLabel = new JLabel();
|
||||
private final JLabel arrowLabel = new JLabel();
|
||||
// Determines if this header column is being used to order the list
|
||||
private boolean ordering = false;
|
||||
|
||||
WorldTableHeader(String title, boolean ordered, boolean ascending, @Nonnull Runnable onRefresh)
|
||||
{
|
||||
setLayout(new BorderLayout(5, 0));
|
||||
setBorder(new CompoundBorder(
|
||||
BorderFactory.createMatteBorder(0, 0, 0, 1, ColorScheme.MEDIUM_GRAY_COLOR),
|
||||
new EmptyBorder(0, 5, 0, 2)));
|
||||
setBackground(ColorScheme.SCROLL_TRACK_COLOR);
|
||||
|
||||
addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent mouseEvent)
|
||||
{
|
||||
textLabel.setForeground(HIGHLIGHT_COLOR);
|
||||
if (!ordering)
|
||||
{
|
||||
arrowLabel.setIcon(HIGHLIGHT_ARROW_UP);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent mouseEvent)
|
||||
{
|
||||
if (!ordering)
|
||||
{
|
||||
textLabel.setForeground(ARROW_COLOR);
|
||||
arrowLabel.setIcon(ARROW_UP);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
textLabel.setText(title);
|
||||
textLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
final JMenuItem refresh = new JMenuItem("Refresh worlds");
|
||||
refresh.addActionListener(e ->
|
||||
{
|
||||
onRefresh.run();
|
||||
});
|
||||
|
||||
final JPopupMenu popupMenu = new JPopupMenu();
|
||||
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
popupMenu.add(refresh);
|
||||
|
||||
textLabel.setComponentPopupMenu(popupMenu);
|
||||
setComponentPopupMenu(popupMenu);
|
||||
|
||||
highlight(ordered, ascending);
|
||||
|
||||
add(textLabel, BorderLayout.WEST);
|
||||
add(arrowLabel, BorderLayout.EAST);
|
||||
}
|
||||
|
||||
/**
|
||||
* The labels inherit the parent's mouse listeners.
|
||||
*/
|
||||
@Override
|
||||
public void addMouseListener(MouseListener mouseListener)
|
||||
{
|
||||
super.addMouseListener(mouseListener);
|
||||
textLabel.addMouseListener(mouseListener);
|
||||
arrowLabel.addMouseListener(mouseListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this column header is being used to order, then it should be
|
||||
* highlighted, changing it's font color and icon.
|
||||
*/
|
||||
public void highlight(boolean on, boolean ascending)
|
||||
{
|
||||
ordering = on;
|
||||
arrowLabel.setIcon(on ? (ascending ? HIGHLIGHT_ARROW_DOWN : HIGHLIGHT_ARROW_UP) : ARROW_UP);
|
||||
textLabel.setForeground(on ? HIGHLIGHT_COLOR : ARROW_COLOR);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Psikoi <https://github.com/Psikoi>
|
||||
* 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.worldhopper;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.http.api.worlds.World;
|
||||
import net.runelite.http.api.worlds.WorldRegion;
|
||||
import net.runelite.http.api.worlds.WorldType;
|
||||
|
||||
class WorldTableRow extends JPanel
|
||||
{
|
||||
private static final ImageIcon FLAG_AUS;
|
||||
private static final ImageIcon FLAG_UK;
|
||||
private static final ImageIcon FLAG_US;
|
||||
private static final ImageIcon FLAG_GER;
|
||||
|
||||
private static final int WORLD_COLUMN_WIDTH = 60;
|
||||
private static final int PLAYERS_COLUMN_WIDTH = 40;
|
||||
private static final int PING_COLUMN_WIDTH = 35;
|
||||
|
||||
private static final Color CURRENT_WORLD = new Color(66, 227, 17);
|
||||
private static final Color DANGEROUS_WORLD = new Color(251, 62, 62);
|
||||
private static final Color TOURNAMENT_WORLD = new Color(79, 145, 255);
|
||||
private static final Color MEMBERS_WORLD = new Color(210, 193, 53);
|
||||
private static final Color FREE_WORLD = new Color(200, 200, 200);
|
||||
private static final Color LEAGUE_WORLD = new Color(133, 177, 178);
|
||||
|
||||
static
|
||||
{
|
||||
FLAG_AUS = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_aus.png"));
|
||||
FLAG_UK = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_uk.png"));
|
||||
FLAG_US = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_us.png"));
|
||||
FLAG_GER = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_ger.png"));
|
||||
}
|
||||
|
||||
private final JMenuItem favoriteMenuOption = new JMenuItem();
|
||||
|
||||
private JLabel worldField;
|
||||
private JLabel playerCountField;
|
||||
private JLabel activityField;
|
||||
private JLabel pingField;
|
||||
private final BiConsumer<World, Boolean> onFavorite;
|
||||
|
||||
@Getter
|
||||
private final World world;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int updatedPlayerCount;
|
||||
|
||||
private int ping;
|
||||
|
||||
private Color lastBackground;
|
||||
|
||||
WorldTableRow(World world, boolean current, boolean favorite, Integer ping, Consumer<World> onSelect, BiConsumer<World, Boolean> onFavorite)
|
||||
{
|
||||
this.world = world;
|
||||
this.onFavorite = onFavorite;
|
||||
this.updatedPlayerCount = world.getPlayers();
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(new EmptyBorder(2, 0, 2, 0));
|
||||
|
||||
addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.getClickCount() == 2)
|
||||
{
|
||||
if (onSelect != null)
|
||||
{
|
||||
onSelect.accept(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.getClickCount() == 2)
|
||||
{
|
||||
setBackground(getBackground().brighter());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.getClickCount() == 2)
|
||||
{
|
||||
setBackground(getBackground().darker());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent mouseEvent)
|
||||
{
|
||||
WorldTableRow.this.lastBackground = getBackground();
|
||||
setBackground(getBackground().brighter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent mouseEvent)
|
||||
{
|
||||
setBackground(lastBackground);
|
||||
}
|
||||
});
|
||||
|
||||
setFavoriteMenu(favorite);
|
||||
|
||||
final JPopupMenu popupMenu = new JPopupMenu();
|
||||
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
popupMenu.add(favoriteMenuOption);
|
||||
|
||||
setComponentPopupMenu(popupMenu);
|
||||
|
||||
JPanel leftSide = new JPanel(new BorderLayout());
|
||||
JPanel rightSide = new JPanel(new BorderLayout());
|
||||
leftSide.setOpaque(false);
|
||||
rightSide.setOpaque(false);
|
||||
|
||||
JPanel worldField = buildWorldField();
|
||||
worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0));
|
||||
worldField.setOpaque(false);
|
||||
|
||||
JPanel pingField = buildPingField(ping);
|
||||
pingField.setPreferredSize(new Dimension(PING_COLUMN_WIDTH, 0));
|
||||
pingField.setOpaque(false);
|
||||
|
||||
JPanel playersField = buildPlayersField();
|
||||
playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0));
|
||||
playersField.setOpaque(false);
|
||||
|
||||
JPanel activityField = buildActivityField();
|
||||
activityField.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
activityField.setOpaque(false);
|
||||
|
||||
recolour(current);
|
||||
|
||||
leftSide.add(worldField, BorderLayout.WEST);
|
||||
leftSide.add(playersField, BorderLayout.CENTER);
|
||||
rightSide.add(activityField, BorderLayout.CENTER);
|
||||
rightSide.add(pingField, BorderLayout.EAST);
|
||||
|
||||
add(leftSide, BorderLayout.WEST);
|
||||
add(rightSide, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
void setFavoriteMenu(boolean favorite)
|
||||
{
|
||||
String favoriteAction = favorite ?
|
||||
"Remove " + world.getId() + " from favorites" :
|
||||
"Add " + world.getId() + " to favorites";
|
||||
|
||||
favoriteMenuOption.setText(favoriteAction);
|
||||
|
||||
for (ActionListener listener : favoriteMenuOption.getActionListeners())
|
||||
{
|
||||
favoriteMenuOption.removeActionListener(listener);
|
||||
}
|
||||
|
||||
favoriteMenuOption.addActionListener(e ->
|
||||
{
|
||||
onFavorite.accept(world, !favorite);
|
||||
});
|
||||
}
|
||||
|
||||
void updatePlayerCount(int playerCount)
|
||||
{
|
||||
this.updatedPlayerCount = playerCount;
|
||||
playerCountField.setText(playerCountString(playerCount));
|
||||
}
|
||||
|
||||
private static String playerCountString(int playerCount)
|
||||
{
|
||||
return playerCount < 0 ? "OFF" : Integer.toString(playerCount);
|
||||
}
|
||||
|
||||
void setPing(int ping)
|
||||
{
|
||||
this.ping = ping;
|
||||
pingField.setText(ping <= 0 ? "-" : Integer.toString(ping));
|
||||
}
|
||||
|
||||
void hidePing()
|
||||
{
|
||||
pingField.setText("-");
|
||||
}
|
||||
|
||||
void showPing()
|
||||
{
|
||||
setPing(ping); // to update pingField
|
||||
}
|
||||
|
||||
int getPing()
|
||||
{
|
||||
return ping;
|
||||
}
|
||||
|
||||
public void recolour(boolean current)
|
||||
{
|
||||
playerCountField.setForeground(current ? CURRENT_WORLD : Color.WHITE);
|
||||
pingField.setForeground(current ? CURRENT_WORLD : Color.WHITE);
|
||||
|
||||
if (current)
|
||||
{
|
||||
activityField.setForeground(CURRENT_WORLD);
|
||||
worldField.setForeground(CURRENT_WORLD);
|
||||
return;
|
||||
}
|
||||
else if (world.getTypes().contains(WorldType.PVP)
|
||||
|| world.getTypes().contains(WorldType.HIGH_RISK)
|
||||
|| world.getTypes().contains(WorldType.DEADMAN))
|
||||
{
|
||||
activityField.setForeground(DANGEROUS_WORLD);
|
||||
}
|
||||
else if (world.getTypes().contains(WorldType.LEAGUE))
|
||||
{
|
||||
activityField.setForeground(LEAGUE_WORLD);
|
||||
}
|
||||
else if (world.getTypes().contains(WorldType.TOURNAMENT))
|
||||
{
|
||||
activityField.setForeground(TOURNAMENT_WORLD);
|
||||
}
|
||||
else
|
||||
{
|
||||
activityField.setForeground(Color.WHITE);
|
||||
}
|
||||
|
||||
worldField.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the players list field (containing the amount of players logged in that world).
|
||||
*/
|
||||
private JPanel buildPlayersField()
|
||||
{
|
||||
JPanel column = new JPanel(new BorderLayout());
|
||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||
|
||||
playerCountField = new JLabel(playerCountString(world.getPlayers()));
|
||||
playerCountField.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
column.add(playerCountField, BorderLayout.WEST);
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
private JPanel buildPingField(Integer ping)
|
||||
{
|
||||
JPanel column = new JPanel(new BorderLayout());
|
||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||
|
||||
pingField = new JLabel("-");
|
||||
pingField.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
column.add(pingField, BorderLayout.EAST);
|
||||
|
||||
if (ping != null)
|
||||
{
|
||||
setPing(ping);
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the activity list field (containing that world's activity/theme).
|
||||
*/
|
||||
private JPanel buildActivityField()
|
||||
{
|
||||
JPanel column = new JPanel(new BorderLayout());
|
||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||
|
||||
activityField = new JLabel(world.getActivity());
|
||||
activityField.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
column.add(activityField, BorderLayout.WEST);
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the world list field (containing the country's flag and the world index).
|
||||
*/
|
||||
private JPanel buildWorldField()
|
||||
{
|
||||
JPanel column = new JPanel(new BorderLayout(7, 0));
|
||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||
|
||||
worldField = new JLabel(world.getId() + "");
|
||||
|
||||
ImageIcon flagIcon = getFlag(world.getRegion());
|
||||
if (flagIcon != null)
|
||||
{
|
||||
JLabel flag = new JLabel(flagIcon);
|
||||
column.add(flag, BorderLayout.WEST);
|
||||
}
|
||||
column.add(worldField, BorderLayout.CENTER);
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
private static ImageIcon getFlag(WorldRegion region)
|
||||
{
|
||||
if (region == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (region)
|
||||
{
|
||||
case UNITED_STATES_OF_AMERICA:
|
||||
return FLAG_US;
|
||||
case UNITED_KINGDOM:
|
||||
return FLAG_UK;
|
||||
case AUSTRALIA:
|
||||
return FLAG_AUS;
|
||||
case GERMANY:
|
||||
return FLAG_GER;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.worldhopper.ping;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
interface IPHlpAPI extends Library
|
||||
{
|
||||
IPHlpAPI INSTANCE = Native.loadLibrary("IPHlpAPI", IPHlpAPI.class);
|
||||
|
||||
Pointer IcmpCreateFile();
|
||||
|
||||
boolean IcmpCloseHandle(Pointer handle);
|
||||
|
||||
int IcmpSendEcho(Pointer IcmpHandle, int DestinationAddress, Pointer RequestData, short RequestSize, Pointer RequestOptions, IcmpEchoReply ReplyBuffer, int ReplySize, int Timeout);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.worldhopper.ping;
|
||||
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.platform.win32.WinDef;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class IcmpEchoReply extends Structure
|
||||
{
|
||||
private static final int IP_OPTION_INFO_SIZE = 1 + 1 + 1 + 1 + (Native.POINTER_SIZE == 8 ? 12 : 4); // on 64bit vms add 4 byte padding
|
||||
public static final int SIZE = 4 + 4 + 4 + 2 + 2 + Native.POINTER_SIZE + IP_OPTION_INFO_SIZE;
|
||||
|
||||
public WinDef.ULONG address;
|
||||
public WinDef.ULONG status;
|
||||
public WinDef.ULONG roundTripTime;
|
||||
public WinDef.USHORT dataSize;
|
||||
public WinDef.USHORT reserved;
|
||||
public WinDef.PVOID data;
|
||||
public WinDef.UCHAR ttl;
|
||||
public WinDef.UCHAR tos;
|
||||
public WinDef.UCHAR flags;
|
||||
public WinDef.UCHAR optionsSize;
|
||||
public WinDef.PVOID optionsData;
|
||||
|
||||
IcmpEchoReply(Pointer p)
|
||||
{
|
||||
super(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getFieldOrder()
|
||||
{
|
||||
return Arrays.asList("address", "status", "roundTripTime", "dataSize", "reserved", "data", "ttl", "tos", "flags", "optionsSize", "optionsData");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.worldhopper.ping;
|
||||
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.Pointer;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.util.OSType;
|
||||
import net.runelite.http.api.worlds.World;
|
||||
|
||||
@Slf4j
|
||||
public class Ping
|
||||
{
|
||||
private static final String RUNELITE_PING = "RuneLitePing";
|
||||
|
||||
private static final int TIMEOUT = 2000;
|
||||
private static final int PORT = 43594;
|
||||
|
||||
public static int ping(World world)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (OSType.getOSType())
|
||||
{
|
||||
case Windows:
|
||||
return windowsPing(world);
|
||||
default:
|
||||
return tcpPing(world);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("error pinging", ex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int windowsPing(World world) throws UnknownHostException
|
||||
{
|
||||
IPHlpAPI ipHlpAPI = IPHlpAPI.INSTANCE;
|
||||
Pointer ptr = ipHlpAPI.IcmpCreateFile();
|
||||
InetAddress inetAddress = InetAddress.getByName(world.getAddress());
|
||||
byte[] address = inetAddress.getAddress();
|
||||
String dataStr = RUNELITE_PING;
|
||||
int dataLength = dataStr.length() + 1;
|
||||
Pointer data = new Memory(dataLength);
|
||||
data.setString(0L, dataStr);
|
||||
IcmpEchoReply icmpEchoReply = new IcmpEchoReply(new Memory(IcmpEchoReply.SIZE + dataLength));
|
||||
assert icmpEchoReply.size() == IcmpEchoReply.SIZE;
|
||||
int packed = (address[0] & 0xff) | ((address[1] & 0xff) << 8) | ((address[2] & 0xff) << 16) | ((address[3] & 0xff) << 24);
|
||||
int ret = ipHlpAPI.IcmpSendEcho(ptr, packed, data, (short) (dataLength), Pointer.NULL, icmpEchoReply, IcmpEchoReply.SIZE + dataLength, TIMEOUT);
|
||||
if (ret != 1)
|
||||
{
|
||||
ipHlpAPI.IcmpCloseHandle(ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rtt = Math.toIntExact(icmpEchoReply.roundTripTime.longValue());
|
||||
ipHlpAPI.IcmpCloseHandle(ptr);
|
||||
|
||||
return rtt;
|
||||
}
|
||||
|
||||
private static int tcpPing(World world) throws IOException
|
||||
{
|
||||
try (Socket socket = new Socket())
|
||||
{
|
||||
socket.setSoTimeout(TIMEOUT);
|
||||
InetAddress inetAddress = InetAddress.getByName(world.getAddress());
|
||||
long start = System.nanoTime();
|
||||
socket.connect(new InetSocketAddress(inetAddress, PORT));
|
||||
long end = System.nanoTime();
|
||||
return (int) ((end - start) / 1000000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020, melky <https://github.com/melkypie>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum AgilityCourseLocation
|
||||
{
|
||||
AGILITY_PYRAMID("Agility Pyramid", new WorldPoint(3347, 2827, 0)),
|
||||
AL_KHARID_ROOFTOP_COURSE("Al Kharid Rooftop Course", new WorldPoint(3272, 3195, 0)),
|
||||
APE_ATOLL_AGILITY_COURSE("Ape Atoll Agility Course", new WorldPoint(2752, 2742, 0)),
|
||||
ARDOUGNE_ROOFTOP_COURSE("Ardougne Rooftop Course", new WorldPoint(2673, 3298, 0)),
|
||||
BARBARIAN_OUTPOST_AGILITY_COURSE("Barbarian Outpost Agility Course", new WorldPoint(2544, 3569, 0)),
|
||||
BRIMHAVEN_AGILITY_ARENA("Brimhaven Agility Arena", new WorldPoint(2806, 3193, 0)),
|
||||
CANIFIS_ROOFTOP_COURSE("Canifis Rooftop Course", new WorldPoint(3506, 3490, 0)),
|
||||
DRAYNOR_VILLAGE_ROOFTOP_COURSE("Draynor Village Rooftop Course", new WorldPoint(3103, 3279, 0)),
|
||||
FALADOR_ROOFTOP_COURSE("Falador Rooftop Course", new WorldPoint(3035, 3342, 0)),
|
||||
GNOME_STRONGHOLD_AGILITY_COURSE("Gnome Stronghold Agility Course", new WorldPoint(2474, 3436, 0)),
|
||||
PENGUIN_AGILITY_COURSE("Penguin Agility Course", new WorldPoint(2638, 4041, 0)),
|
||||
POLLNIVNEACH_ROOFTOP_COURSE("Pollnivneach Rooftop Course", new WorldPoint(3350, 2963, 0)),
|
||||
PRIFDDINAS_AGILITY_COURSE("Prifddinas Agility Course", new WorldPoint(3253, 6109, 0)),
|
||||
RELLEKKA_ROOFTOP_COURSE("Rellekka Rooftop Course", new WorldPoint(2624, 3677, 0)),
|
||||
SEERS_VILLAGE_ROOFTOP_COURSE("Seers' Village Rooftop Course", new WorldPoint(2728, 3488, 0)),
|
||||
VARROCK_ROOFTOP_COURSE("Varrock Rooftop Course", new WorldPoint(3219, 3414, 0)),
|
||||
WEREWOLF_AGILITY_COURSE("Werewolf Agility Course", new WorldPoint(3542, 3463, 0)),
|
||||
WILDERNESS_AGILITY_COURSE("Wilderness Agility Course", new WorldPoint(2997, 3916, 0));
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
private final boolean rooftopCourse;
|
||||
|
||||
AgilityCourseLocation(String tooltip, WorldPoint location)
|
||||
{
|
||||
this.tooltip = tooltip;
|
||||
this.location = location;
|
||||
this.rooftopCourse = this.name().contains("ROOFTOP_COURSE");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2020, melky <https://github.com/melkypie>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class AgilityCoursePoint extends WorldMapPoint
|
||||
{
|
||||
AgilityCoursePoint(AgilityCourseLocation data, BufferedImage icon, boolean showTooltip)
|
||||
{
|
||||
super(data.getLocation(), icon);
|
||||
|
||||
if (showTooltip)
|
||||
{
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
import net.runelite.client.game.AgilityShortcut;
|
||||
|
||||
class AgilityShortcutPoint extends WorldMapPoint
|
||||
{
|
||||
AgilityShortcutPoint(AgilityShortcut data, BufferedImage icon, boolean showTooltip)
|
||||
{
|
||||
super(data.getWorldMapLocation(), icon);
|
||||
|
||||
if (showTooltip)
|
||||
{
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arman S <https://github.com/Rman887>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum DungeonLocation
|
||||
{
|
||||
ABANDONED_MINE("Abandoned Mine", new WorldPoint(3439, 3232, 0)),
|
||||
ABANDONED_MINE_SECRET("Abandoned Mine (secret entrance)", new WorldPoint(3452, 3244, 0)),
|
||||
ANCIENT_CAVERN("Ancient Cavern", new WorldPoint(2511, 3508, 0)),
|
||||
APE_ATOLL("Ape Atoll Dungeon", new WorldPoint(2762, 2703, 0)),
|
||||
ARDOUGNE_CASTLE("Ardougne Castle basement", new WorldPoint(2569, 3296, 0)),
|
||||
ARDOUGNE_RAT_PITS("Ardougne Rat Pits", new WorldPoint(2560, 3320, 0)),
|
||||
ARDOUGNE_SEWERS_N("Ardougne Sewers", new WorldPoint(2631, 3294, 0)),
|
||||
ARDOUGNE_SEWERS_S("Ardougne Sewers", new WorldPoint(2586, 3235, 0)),
|
||||
ARDOUGNE_SEWERS_W("Ardougne Sewers", new WorldPoint(2528, 3303, 0)),
|
||||
ASGARNIAN_ICE("Asgarnian Ice Dungeon", new WorldPoint(3007, 3150, 0)),
|
||||
BRIMHAVEN_AGILITY("Brimhaven Agility Arena", new WorldPoint(2808, 3194, 0)),
|
||||
BRIMHAVEN_N("Brimhaven Dungeon", new WorldPoint(2743, 3154, 0)),
|
||||
BRIMHAVEN_S("Brimhaven Dungeon", new WorldPoint(2759, 3062, 0)),
|
||||
BRIMSTAILS_CAVE("Brimstail's Cave", new WorldPoint(2402, 3419, 0)),
|
||||
CATACOMBS_OF_KOUREND("Catacombs of Kourend", new WorldPoint(1636, 3673, 0)),
|
||||
CHAMBERS_OF_XERIC("Chambers of Xeric", new WorldPoint(1232, 3573, 0)),
|
||||
CHAMPIONS_CHALLENGE("Champions' Challenge", new WorldPoint(3188, 3355, 0)),
|
||||
CHAOS_DRUID_TOWER("Chaos Druid Tower dungeon", new WorldPoint(2561, 3356, 0)),
|
||||
CHASM_OF_FIRE("Chasm of Fire", new WorldPoint(1432, 3670, 0)),
|
||||
CLOCK_TOWER("Clock Tower Dungeon", new WorldPoint(2568, 3229, 0)),
|
||||
CORPOREAL_BEAST("Corporeal Beast cave", new WorldPoint(3202, 3681, 0)),
|
||||
CORSAIR_COVE_E("Corsair Cove Dungeon", new WorldPoint(2522, 2861, 0)),
|
||||
CORSAIR_COVE_N("Corsair Cove Dungeon", new WorldPoint(2482, 2891, 0)),
|
||||
CRABCLAW_CAVES("Crabclaw Caves", new WorldPoint(1643, 3449, 0)),
|
||||
CRABCLAW_CAVES_TUNNEL("Crabclaw Caves Tunnel (quest)", new WorldPoint(1643, 3449, 0)),
|
||||
CRANDOR("Crandor Dungeon", new WorldPoint(2833, 3256, 0)),
|
||||
CRASH_ISLAND("Crash Island Dungeon", new WorldPoint(2920, 2721, 0)),
|
||||
DEEP_WILDERNESS("Deep Wilderness Dungeon", new WorldPoint(3044, 3924, 0)),
|
||||
DRAYNOR_MANOR_E("Draynor Manor basement", new WorldPoint(3114, 3357, 0)),
|
||||
DRAYNOR_MANOR_W("Draynor Manor basement", new WorldPoint(3091, 3362, 0)),
|
||||
DRAYNOR_SEWERS_NW("Draynor Sewers", new WorldPoint(3083, 3272, 0)),
|
||||
DRAYNOR_SEWERS_SE("Draynor Sewers", new WorldPoint(3117, 3244, 0)),
|
||||
DWARVEN_MINE("Dwarven Mine", new WorldPoint(3017, 3450, 0)),
|
||||
DWARVEN_MINE_STAIRS("Dwarven Mine", new WorldPoint(3058, 3377, 0)),
|
||||
ECTOFUNTUS("Ectofuntus dungeon", new WorldPoint(3651, 3519, 0)),
|
||||
EDGEVILLE("Edgeville Dungeon", new WorldPoint(3096, 3469, 0)),
|
||||
EDGEVILLE_SHED("Edgeville Dungeon", new WorldPoint(3115, 3452, 0)),
|
||||
EDGEVILLE_WILDERNESS("Edgeville Dungeon", new WorldPoint(3087, 3571, 0)),
|
||||
ENTRANA("Entrana Dungeon", new WorldPoint(2819, 3374, 0)),
|
||||
ETCETERIA("Miscellania and Etceteria Dungeon", new WorldPoint(2619, 3865, 0)),
|
||||
FALADOR_MOLE_NW("Mole Hole", new WorldPoint(2985, 3387, 0)),
|
||||
FALADOR_MOLE_SE("Mole Hole", new WorldPoint(2997, 3376, 0)),
|
||||
FORSAKEN_TOWER("Forsaken Tower basement", new WorldPoint(1381, 3825, 0)),
|
||||
FORTHOS_E("Forthos Dungeon", new WorldPoint(1701, 3574, 0)),
|
||||
FORTHOS_W("Forthos Dungeon", new WorldPoint(1669, 3567, 0)),
|
||||
FREMENNIK_SLAYER("Fremennik Slayer Dungeon", new WorldPoint(2796, 3615, 0)),
|
||||
GOBLIN_CAVE("Goblin Cave", new WorldPoint(2622, 3393, 0)),
|
||||
GOD_WARS("God Wars Dungeon", new WorldPoint(2917, 3747, 0)),
|
||||
GRAND_TREE("Grand Tree Tunnels", new WorldPoint(2464, 3496, 0)),
|
||||
GAUNTLET("The Gauntlet", new WorldPoint(3227, 6116, 0)),
|
||||
HAM_HIDEOUT("H.A.M. Hideout", new WorldPoint(3164, 3252, 0)),
|
||||
HEROES_GUILD("Heroes' Guild mine", new WorldPoint(2891, 3507, 0)),
|
||||
HESPORI("Hespori Patch", new WorldPoint(1231, 3729, 0)),
|
||||
ICE_QUEEN("Ice Queen's Lair", new WorldPoint(2846, 3516, 0)),
|
||||
ICE_QUEEN_E("Ice Queen's Lair", new WorldPoint(2856, 3519, 0)),
|
||||
ICE_QUEEN_W("Ice Queen's Lair", new WorldPoint(2822, 3510, 0)),
|
||||
ICE_TROLL_E("Ice Troll Caves", new WorldPoint(2400, 3889, 0)),
|
||||
ICE_TROLL_W("Ice Troll Caves", new WorldPoint(2315, 3894, 0)),
|
||||
IORWERTH("Iorwerth Dungeon", new WorldPoint(3224, 6044, 0)),
|
||||
IORWERTH_CAMP_CAVE("Iorwerth Camp cave", new WorldPoint(2200, 3262, 0)),
|
||||
IORWERTH_CAMP_CAVE_PRIF("Iorwerth Camp cave", new WorldPoint(3224, 6014, 0)),
|
||||
JOGRE("Jogre Dungeon", new WorldPoint(2824, 3118, 0)),
|
||||
JORMUNGANDS_PRISON("Jormungand's Prison", new WorldPoint(2464, 4012, 0)),
|
||||
KALPHITE_CAVE("Kalphite Cave", new WorldPoint(3319, 3122, 0)),
|
||||
KALPHITE_LAIR("Kalphite Lair", new WorldPoint(3226, 3108, 0)),
|
||||
KARAMJA_VOLCANO("Karamja Dungeon", new WorldPoint(2855, 3168, 0)),
|
||||
KARUULM_SLAYER("Karuulm Slayer Dungeon", new WorldPoint(1308, 3807, 0)),
|
||||
KING_BLACK_DRAGON("King Black Dragon Lair", new WorldPoint(3016, 3849, 0)),
|
||||
KELDAGRIM("Keldagrim Entrance", new WorldPoint(2730, 3713, 0)),
|
||||
KELDAGRIM_ENTRANCE_MOUNTAIN("Keldagrim Entrance", new WorldPoint(2795, 3718, 0)),
|
||||
KRAKEN_BOSS("Kraken (boss)", new WorldPoint(2279, 10017, 0)),
|
||||
KRAKEN_COVE("Kraken Cove", new WorldPoint(2277, 3611, 0)),
|
||||
LAVA_MAZE("Lava Maze Dungeon", new WorldPoint(3068, 3856, 0)),
|
||||
LEGENDS_GUILD("Legends' Guild dungeon", new WorldPoint(2723, 3375, 0)),
|
||||
LIGHTHOUSE("Lighthouse basement", new WorldPoint(2508, 3644, 0)),
|
||||
LIZARDMAN_CAVES("Lizardman Caves", new WorldPoint(1306, 3574, 0)),
|
||||
LIZARDMAN_TEMPLE_E("Lizardman Temple", new WorldPoint(1329, 3669, 0)),
|
||||
LIZARDMAN_TEMPLE_N("Lizardman Temple", new WorldPoint(1311, 3686, 0)),
|
||||
LIZARDMAN_TEMPLE_S("Lizardman Temple", new WorldPoint(1313, 3663, 0)),
|
||||
LIZARDMAN_TEMPLE_W("Lizardman Temple", new WorldPoint(1291, 3657, 0)),
|
||||
LUMBRIDGE_CASTLE("Lumbridge Castle cellar", new WorldPoint(3208, 3218, 0)),
|
||||
LUMBRIDGE_SWAMP("Lumbridge Swamp Caves", new WorldPoint(3168, 3172, 0)),
|
||||
LUNAR_ISLE("Lunar Isle Mine", new WorldPoint(2141, 3944, 0)),
|
||||
MAGE_ARENA("Mage Arena Bank", new WorldPoint(3089, 3956, 0)),
|
||||
MELZARS_MAZE("Melzar's Maze basement", new WorldPoint(2923, 3250, 0)),
|
||||
MINING_GUILD("Mining Guild basement", new WorldPoint(3018, 3339, 0)),
|
||||
MISCELLANIA("Miscellania and Etceteria Dungeon", new WorldPoint(2508, 3846, 0)),
|
||||
MOS_LE_HARMLESS("Mos Le'Harmless Cave", new WorldPoint(3747, 2973, 0)),
|
||||
MOS_LE_HARMLESS_ISLAND_E("Mos Le'Harmless Cave", new WorldPoint(3829, 3062, 0)),
|
||||
MOS_LE_HARMLESS_ISLAND_W("Mos Le'Harmless Cave", new WorldPoint(3814, 3062, 0)),
|
||||
MOTHERLODE_MINE("Motherlode Mine", new WorldPoint(3059, 9764, 0)),
|
||||
MOTHERLODE_MINE_GUILD("Motherlode Mine", new WorldPoint(3055, 9744, 0)),
|
||||
MYREQUE_HIDEOUT_CANAFIS("Myreque Hideout", new WorldPoint(3494, 3464, 0)),
|
||||
MYREQUE_HIDEOUT_SWAMP("Myreque Hideout", new WorldPoint(3508, 3448, 0)),
|
||||
MYTH_GUILD("Myths' Guild dungeon", new WorldPoint(2456, 2847, 0)),
|
||||
MYTH_GUILD_WRATH("Myths' Guild dungeon", new WorldPoint(2444, 2819, 0)),
|
||||
OBSERVATORY_NE("Observatory Dungeon", new WorldPoint(2458, 3186, 0)),
|
||||
OBSERVATORY_SW("Observatory Dungeon", new WorldPoint(2436, 3163, 0)),
|
||||
OGRE_ENCLAVE("Ogre Enclave", new WorldPoint(2505, 3039, 0)),
|
||||
OURANIA_CAVE("Ourania Cave", new WorldPoint(2451, 3231, 0)),
|
||||
PATERDOMUS("Paterdomus basement", new WorldPoint(3404, 3506, 0)),
|
||||
PORT_PHASMATYS_BREWERY("Port Phasmatys Brewery", new WorldPoint(3679, 3498, 0)),
|
||||
PORT_SARIM_RAT_PITS("Port Sarim Rat Pits", new WorldPoint(3017, 3232, 0)),
|
||||
QUIDAMORTEM_CAVE("Quidamortem Cave", new WorldPoint(1213, 3559, 0)),
|
||||
RED_CHIN_HUNTING("Red chinchompa hunting ground", new WorldPoint(2525, 2894, 0)),
|
||||
REVENANT_CAVES_N("Revenant Caves", new WorldPoint(3124, 3832, 0)),
|
||||
REVENANT_CAVES_S("Revenant Caves", new WorldPoint(3074, 3655, 0)),
|
||||
RIVER_ELID("River Elid Dungeon", new WorldPoint(3370, 3132, 0)),
|
||||
RIVER_KELDA("River Kelda", new WorldPoint(2835, 10112, 0)),
|
||||
SALT_MINE("Salt Mine", new WorldPoint(2866, 3941, 0)),
|
||||
SCAVID_CAVES_N("Scavid Caves", new WorldPoint(2521, 3070, 0)),
|
||||
SCAVID_CAVES_NE("Scavid Caves", new WorldPoint(2540, 3054, 0)),
|
||||
SCAVID_CAVES_NEE("Scavid Caves", new WorldPoint(2552, 3054, 0)),
|
||||
SCAVID_CAVES_E("Scavid Caves", new WorldPoint(2551, 3035, 0)),
|
||||
SCAVID_CAVES_ISLAND_E("Scavid Caves (island)", new WorldPoint(2574, 3028, 0)),
|
||||
SCAVID_CAVES_ISLAND_W("Scavid Caves (island)", new WorldPoint(2500, 2991, 0)),
|
||||
SCAVID_CAVES_S("Scavid Caves", new WorldPoint(2528, 3014, 0)),
|
||||
SCAVID_CAVES_SEE("Scavid Caves", new WorldPoint(2561, 3025, 0)),
|
||||
SCORPIA_E("Scorpia cave", new WorldPoint(3243, 3949, 0)),
|
||||
SCORPIA_N("Scorpia cave", new WorldPoint(3230, 3952, 0)),
|
||||
SCORPIA_S("Scorpia cave", new WorldPoint(3231, 3936, 0)),
|
||||
SHADE_CATACOMBS("Shade Catacombs", new WorldPoint(3484, 3321, 0)),
|
||||
SHAYZIEN_CRYPTS("Shayzien Crypts", new WorldPoint(1482, 3549, 0)),
|
||||
SHILO_VILLAGE_MINE("Shilo Village mine", new WorldPoint(2823, 3001, 0)),
|
||||
SISTERHOOD_SANCTUARY("Sisterhood Sanctuary", new WorldPoint(3727, 3300, 0)),
|
||||
SISTERHOOD_SANCTUARY_LAB("Sisterhood Sanctuary", new WorldPoint(3724, 3356, 0)),
|
||||
SLAYER_TOWER("Slayer Tower basement", new WorldPoint(3416, 3535, 0)),
|
||||
SLEPE_BASEMENT("Slepe basement", new WorldPoint(3718, 3307, 0)),
|
||||
SMOKE_DEVIL("Smoke Devil Dungeon", new WorldPoint(2411, 3061, 0)),
|
||||
SMOKE_DEVIL_BOSS("Thermonuclear Smoke Devil (boss)", new WorldPoint(2377, 9452, 0)),
|
||||
SMOKE_DUNGEON("Smoke Dungeon", new WorldPoint(3309, 2962, 0)),
|
||||
SOPHANEM("Sophanem Dungeon", new WorldPoint(3314, 2797, 0)),
|
||||
SOURHOG_CAVE("Sourhog Cave", new WorldPoint(3149, 3347, 0)),
|
||||
STRONGHOLD_OF_SECURITY("Stronghold of Security", new WorldPoint(3080, 3420, 0)),
|
||||
STRONGHOLD_SLAYER("Stronghold Slayer Dungeon", new WorldPoint(2427, 3424, 0)),
|
||||
TAVERLEY("Taverley Dungeon", new WorldPoint(2883, 3397, 0)),
|
||||
TAVERLEY_ISLAND("Taverley Dungeon", new WorldPoint(2841, 3424, 0)),
|
||||
TEMPLE_OF_IKOV("Temple of Ikov", new WorldPoint(2676, 3404, 0)),
|
||||
THEATRE_OF_BLOOD("Theatre of Blood", new WorldPoint(3676, 3219, 0)),
|
||||
TOLNAS_RIFT("Tolna's rift", new WorldPoint(3308, 3450, 0)),
|
||||
TOWER_OF_LIFE("Tower of Life dungeon", new WorldPoint(2649, 3213, 0)),
|
||||
TRAHAEARN_MINE("Trahaearn Mine", new WorldPoint(3270, 6049, 0)),
|
||||
TREE_GNOME_VILLAGE("Tree Gnome Village Dungeon", new WorldPoint(2532, 3155, 0)),
|
||||
TROLL_STRONGHOLD("Troll Stronghold", new WorldPoint(2838, 3690, 0)),
|
||||
TROLL_STRONGHOLD_ROOF("Troll Stronghold", new WorldPoint(2830, 3677, 0)),
|
||||
TROLL_STRONGHOLD_MOUNTAIN("Troll Stronghold", new WorldPoint(2826, 3647, 0)),
|
||||
TUTORIAL_ISLAND_E("Tutorial Island mine", new WorldPoint(3110, 3126, 0)),
|
||||
TUTORIAL_ISLAND_W("Tutorial Island mine", new WorldPoint(3087, 3119, 0)),
|
||||
TZHAAR_CITY("TzHaar City (Mor Ul Rek)", new WorldPoint(2862, 9572, 0)),
|
||||
UNDERGROUND_PASS_KANDARIN("Underground Pass", new WorldPoint(2312, 3215, 0)),
|
||||
UNDERGROUND_PASS_TIRANNWN("Underground Pass", new WorldPoint(2433, 3315, 0)),
|
||||
UNDERGROUND_PASS_TIRANNWN_PRIF("Underground Pass", new WorldPoint(3336, 5967, 0)),
|
||||
UNDERWATER("Underwater", new WorldPoint(3765, 3898, 0)),
|
||||
UZER("Ruins of Uzer basement", new WorldPoint(3492, 3090, 0)),
|
||||
VARROCK_SEWERS("Varrock Sewers", new WorldPoint(3236, 3458, 0)),
|
||||
VARROCK_SEWERS_ZOO("Varrock Sewers", new WorldPoint(3229, 3504, 0)),
|
||||
VOLCANIC_MINE("Volcanic Mine", new WorldPoint(3815, 3808, 0)),
|
||||
VTAM_CORP("VTAM Corporation", new WorldPoint(3243, 3383, 0)),
|
||||
WARRENS("The Warrens", new WorldPoint(1812, 3745, 0)),
|
||||
WARRIORS_GUILD("Warriors' Guild basement", new WorldPoint(2832, 3542, 0)),
|
||||
WATERBIRTH("Waterbirth Dungeon", new WorldPoint(2520, 3740, 0)),
|
||||
WATERBIRTH_MOUNTAIN("Waterbirth Dungeon", new WorldPoint(2542, 3741, 0)),
|
||||
WATERBIRTH_SUBLEVELS("Waterbirth Dungeon (sub-levels)", new WorldPoint(2545, 10143, 0)),
|
||||
WEISS_HOLE("Hole (shortcut to boat)", new WorldPoint(2853, 3944, 0)),
|
||||
WEREWOLF_AGILITY("Werewolf Agility Course", new WorldPoint(3542, 3461, 0)),
|
||||
WHITE_WOLF_TUNNEL_E("White Wolf Tunnel", new WorldPoint(2876, 3480, 0)),
|
||||
WHITE_WOLF_TUNNEL_W("White Wolf Tunnel", new WorldPoint(2819, 3484, 0)),
|
||||
WILDERNESS_AGILITY("Wilderness Agility Course Dungeon", new WorldPoint(3004, 3963, 0)),
|
||||
WILDERNESS_GOD_WARS("Wilderness God Wars Dungeon", new WorldPoint(3016, 3739, 0)),
|
||||
WILDERNESS_SLAYER_CAVE_NORTH("Wilderness Slayer Cave", new WorldPoint(3292, 3746, 0)),
|
||||
WILDERNESS_SLAYER_CAVE_SOUTH("Wilderness Slayer Cave", new WorldPoint(3259, 3666, 0)),
|
||||
WITCHAVEN("Witchaven Dungeon", new WorldPoint(2695, 3283, 0)),
|
||||
WIZARDS_GUILD("Wizards' Guild basement", new WorldPoint(2593, 3085, 0)),
|
||||
WIZARDS_TOWER("Wizards' Tower basement", new WorldPoint(3103, 3162, 0)),
|
||||
WOODCUTTING_GUILD("Woodcutting Guild dungeon", new WorldPoint(1603, 3508, 0)),
|
||||
WYVERN_CAVE("Wyvern Cave", new WorldPoint(3745, 3779, 0)),
|
||||
WYVERN_CAVE_TASK("Wyvern Cave (task only)", new WorldPoint(3677, 3854, 0)),
|
||||
YANILLE_AGILITY("Yanille Agility Dungeon", new WorldPoint(2568, 3122, 0)),
|
||||
YANILLE_AGILITY_CITY("Yanille Agility Dungeon", new WorldPoint(2603, 3078, 0)),
|
||||
ZALCANO("Zalcano's Prison", new WorldPoint(3280, 6059, 0)),
|
||||
ZOGRE_CAVE("Zogre cave", new WorldPoint(2484, 3043, 0));
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
|
||||
DungeonLocation(String tooltip, WorldPoint location)
|
||||
{
|
||||
this.tooltip = tooltip;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arman S <https://github.com/Rman887>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class DungeonPoint extends WorldMapPoint
|
||||
{
|
||||
DungeonPoint(DungeonLocation data, BufferedImage icon)
|
||||
{
|
||||
super(data.getLocation(), icon);
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum FairyRingLocation
|
||||
{
|
||||
AIR("AIR", new WorldPoint(2699, 3249, 0)),
|
||||
AIQ("AIQ", new WorldPoint(2995, 3112, 0)),
|
||||
AJR("AJR", new WorldPoint(2779, 3615, 0)),
|
||||
AJS("AJS", new WorldPoint(2499, 3898, 0)),
|
||||
AKQ("AKQ", new WorldPoint(2318, 3617, 0)),
|
||||
AKS("AKS", new WorldPoint(2570, 2958, 0)),
|
||||
ALP("ALP", new WorldPoint(2502, 3638, 0)),
|
||||
ALQ("ALQ", new WorldPoint(3598, 3496, 0)),
|
||||
ALS("ALS", new WorldPoint(2643, 3497, 0)),
|
||||
BIP("BIP", new WorldPoint(3409, 3326, 0)),
|
||||
BIQ("BIQ", new WorldPoint(3248, 3095, 0)),
|
||||
BIS("BIS", new WorldPoint(2635, 3268, 0)),
|
||||
BJS("BJS", new WorldPoint(2147, 3069, 0)),
|
||||
BKP("BKP", new WorldPoint(2384, 3037, 0)),
|
||||
BKR("BKR", new WorldPoint(3468, 3433, 0)),
|
||||
BLP("BLP", new WorldPoint(2432, 5127, 0)),
|
||||
BLR("BLR", new WorldPoint(2739, 3353, 0)),
|
||||
CIP("CIP", new WorldPoint(2512, 3886, 0)),
|
||||
CIR("CIR", new WorldPoint(1303, 3762, 0)),
|
||||
CIQ("CIQ", new WorldPoint(2527, 3129, 0)),
|
||||
CJR("CJR", new WorldPoint(2704, 3578, 0)),
|
||||
CKR("CKR", new WorldPoint(2800, 3005, 0)),
|
||||
CKS("CKS", new WorldPoint(3446, 3472, 0)),
|
||||
CLP("CLP", new WorldPoint(3081, 3208, 0)),
|
||||
CLS("CLS", new WorldPoint(2681, 3083, 0)),
|
||||
DIP("DIP", new WorldPoint(3039, 4757, 0)),
|
||||
DIS("DIS", new WorldPoint(3109, 3149, 0)),
|
||||
DJP("DJP", new WorldPoint(2657, 3232, 0)),
|
||||
DJR("DJR", new WorldPoint(1452, 3659, 0)),
|
||||
DKP("DKP", new WorldPoint(2899, 3113, 0)),
|
||||
DKR("DKR", new WorldPoint(3126, 3496, 0)),
|
||||
DKS("DKS", new WorldPoint(2743, 3721, 0)),
|
||||
DLQ("DLQ", new WorldPoint(3422, 3018, 0)),
|
||||
DLR("DLR", new WorldPoint(2212, 3101, 0)),
|
||||
CIS("CIS", new WorldPoint(1638, 3868, 0)),
|
||||
CLR("CLR", new WorldPoint(2737, 2739, 0)),
|
||||
ZANARIS("Zanaris", new WorldPoint(2411, 4436, 0));
|
||||
|
||||
private final String code;
|
||||
private final WorldPoint location;
|
||||
|
||||
FairyRingLocation(String code, WorldPoint location)
|
||||
{
|
||||
this.code = code;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class FairyRingPoint extends WorldMapPoint
|
||||
{
|
||||
FairyRingPoint(FairyRingLocation data, BufferedImage icon, boolean showTooltip)
|
||||
{
|
||||
super(data.getLocation(), icon);
|
||||
|
||||
if (showTooltip)
|
||||
{
|
||||
setTooltip("Fairy Ring - " + data.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Torkel Velure <https://github.com/TorkelV>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum FarmingPatchLocation
|
||||
{
|
||||
ALLOTMENT("Allotment",
|
||||
new WorldPoint(3793, 2836, 0),
|
||||
new WorldPoint(1269, 3730, 0)
|
||||
),
|
||||
ALLOTMENT_FLOWER("Allotment/Flower", new WorldPoint(3289, 6100, 0)),
|
||||
ALLOTMENT_HERB_FLOWER("Allotment/Herb/Flower",
|
||||
new WorldPoint(1729, 3558, 0),
|
||||
new WorldPoint(3598, 3524, 0),
|
||||
new WorldPoint(3052, 3309, 0),
|
||||
new WorldPoint(2810, 3462, 0),
|
||||
new WorldPoint(2663, 3375, 0)
|
||||
),
|
||||
ANIMA_HERB("Anima/Herb", new WorldPoint(1235, 3724, 0)),
|
||||
BELLADONNA("Belladonna", new WorldPoint(3084, 3356, 0)),
|
||||
BUSH("Bush",
|
||||
new WorldPoint(2938, 3223, 0),
|
||||
new WorldPoint(2589, 3862, 0),
|
||||
new WorldPoint(3182, 3356, 0),
|
||||
new WorldPoint(2615, 3224, 0)
|
||||
),
|
||||
BUSH_FLOWER("Bush/Flower", new WorldPoint(1259, 3729, 0)),
|
||||
CACTUS("Cactus",
|
||||
new WorldPoint(3313, 3201, 0),
|
||||
new WorldPoint(1264, 3745, 0)
|
||||
),
|
||||
CALQUAT("Calquat", new WorldPoint(2793, 3099, 0)),
|
||||
CELASTRUS_FRUIT_TREE("Celastrus/Fruit Tree",
|
||||
new WorldPoint(1242, 3755, 0)
|
||||
),
|
||||
CRYSTAL_TREE("Crystal Tree",
|
||||
new WorldPoint(3292, 6120, 0)
|
||||
),
|
||||
FRUIT_TREE("Fruit Tree",
|
||||
new WorldPoint(2487, 3181, 0),
|
||||
new WorldPoint(2343, 3160, 0),
|
||||
new WorldPoint(2472, 3445, 0),
|
||||
new WorldPoint(2858, 3432, 0),
|
||||
new WorldPoint(2765, 3211, 0)
|
||||
),
|
||||
GRAPES("Grapes", new WorldPoint(1807, 3555, 0)),
|
||||
HARDWOOD("Hardwood",
|
||||
new WorldPoint(3707, 3838, 0)
|
||||
),
|
||||
HERB("Herb",
|
||||
new WorldPoint(3789, 2840, 0),
|
||||
new WorldPoint(2847, 3933, 0),
|
||||
new WorldPoint(2828, 3696, 0)
|
||||
),
|
||||
HESPORI("Hespori", new WorldPoint(1182, 10068, 0)),
|
||||
HOPS("Hops",
|
||||
new WorldPoint(2572, 3102, 0),
|
||||
new WorldPoint(2661, 3523, 0),
|
||||
new WorldPoint(3224, 3313, 0),
|
||||
new WorldPoint(3812, 3334, 0)
|
||||
),
|
||||
MUSHROOM("Mushroom", new WorldPoint(3449, 3471, 0)),
|
||||
REDWOOD("Redwood", new WorldPoint(1233, 3754, 0)),
|
||||
SEAWEED("Seaweed", new WorldPoint(3730, 10271, 0)),
|
||||
SPIRIT_TREE("Spirit Tree",
|
||||
new WorldPoint(3056, 3259, 0),
|
||||
new WorldPoint(1690, 3540, 0),
|
||||
new WorldPoint(3614, 3856, 0),
|
||||
new WorldPoint(2799, 3205, 0),
|
||||
new WorldPoint(1254, 3753, 0)
|
||||
),
|
||||
TREE("Tree",
|
||||
new WorldPoint(3226, 3457, 0),
|
||||
new WorldPoint(2933, 3436, 0),
|
||||
new WorldPoint(3189, 3233, 0),
|
||||
new WorldPoint(2434, 3418, 0),
|
||||
new WorldPoint(3005, 3375, 0),
|
||||
new WorldPoint(1234, 3736, 0)
|
||||
);
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint[] locations;
|
||||
|
||||
FarmingPatchLocation(String description, WorldPoint... locations)
|
||||
{
|
||||
this.tooltip = "Farming patch - " + description;
|
||||
this.locations = locations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Torkel Velure <https://github.com/TorkelV>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class FarmingPatchPoint extends WorldMapPoint
|
||||
{
|
||||
FarmingPatchPoint(WorldPoint point, String tooltip, BufferedImage icon)
|
||||
{
|
||||
super(point, icon);
|
||||
setTooltip(tooltip);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2020, melky <https://github.com/melkypie>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.game.FishingSpot;
|
||||
|
||||
@Getter
|
||||
enum FishingSpotLocation
|
||||
{
|
||||
AL_KHARID(FishingSpot.SHRIMP,
|
||||
new WorldPoint(3274, 3140, 0), new WorldPoint(3266, 3148, 0)),
|
||||
APE_ATOLL_SOUTH_WEST(FishingSpot.SHARK, new WorldPoint(2698, 2703, 0)),
|
||||
BARBARIAN_OUTPOST(FishingSpot.SHRIMP,
|
||||
new WorldPoint(2497, 3548, 0), new WorldPoint(2509, 3562, 0),
|
||||
new WorldPoint(2514, 3575, 0)),
|
||||
BARBARIAN_VILLAGE(FishingSpot.SALMON,
|
||||
new WorldPoint(3103, 3424, 0), new WorldPoint(3109, 3433, 0)),
|
||||
BRAINDEATH_ISLAND(FishingSpot.QUEST_RUM_DEAL,
|
||||
new WorldPoint(2112, 5074, 0), new WorldPoint(2161, 5061, 0),
|
||||
new WorldPoint(2172, 5074, 0)),
|
||||
BRIMHAVEN_QUEST(FishingSpot.QUEST_TAI_BWO_WANNAI_TRIO, new WorldPoint(2767, 3165, 0)),
|
||||
BURGH_DE_ROTT_SOUTH(FishingSpot.SHARK,
|
||||
new WorldPoint(3472, 3192, 0), new WorldPoint(3486, 3182, 0),
|
||||
new WorldPoint(3497, 3174, 0), new WorldPoint(3513, 3177, 0),
|
||||
new WorldPoint(3528, 3164, 0), new WorldPoint(3537, 3177, 0),
|
||||
new WorldPoint(3545, 3179, 0), new WorldPoint(3553, 3177, 0),
|
||||
new WorldPoint(3559, 3173, 0), new WorldPoint(3564, 3174, 0)),
|
||||
CATHERBY(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER, FishingSpot.SHRIMP},
|
||||
new WorldPoint(2836, 3431, 0), new WorldPoint(2844, 3429, 0),
|
||||
new WorldPoint(2853, 3423, 0), new WorldPoint(2859, 3426, 0)),
|
||||
DRAYNOR_VILLAGE(FishingSpot.SHRIMP, new WorldPoint(3084, 3228, 0)),
|
||||
ENTRANA_CENTER(FishingSpot.SALMON,
|
||||
new WorldPoint(2841, 3356, 0), new WorldPoint(2842, 3359, 0),
|
||||
new WorldPoint(2847, 3361, 0)),
|
||||
ENTRANA_DOCK(FishingSpot.SHRIMP,
|
||||
new WorldPoint(2875, 3331, 0), new WorldPoint(2878, 3334, 0),
|
||||
new WorldPoint(2878, 3339, 0), new WorldPoint(2875, 3342, 0)),
|
||||
ETCETERIA_DOCK(FishingSpot.ETCETERIA_LOBSTER, new WorldPoint(2577, 3854, 0)),
|
||||
FAIRY_RING_CKR(FishingSpot.KARAMBWANJI, new WorldPoint(2806, 3014, 0)),
|
||||
FAIRY_RING_DKP(FishingSpot.KARAMBWAN,
|
||||
new WorldPoint(2898, 3119, 0), new WorldPoint(2911, 3119, 0)),
|
||||
FARMING_GUILD_SOUTH_EAST(FishingSpot.SALMON, new WorldPoint(1269, 3707, 0)),
|
||||
FARMING_GUILD_SOUTH_WEST1(FishingSpot.SHARK, new WorldPoint(1209, 3687, 0)),
|
||||
FARMING_GUILD_SOUTH_WEST2(FishingSpot.SHARK, new WorldPoint(1221, 3714, 0)),
|
||||
FARMING_GUILD_WEST(FishingSpot.SHARK,
|
||||
new WorldPoint(1199, 3736, 0), new WorldPoint(1208, 3749, 0)),
|
||||
FELDIP_HILLS_SOUTH(FishingSpot.SHRIMP, new WorldPoint(2511, 2838, 0)),
|
||||
FISHING_CONTEST(FishingSpot.QUEST_FISHING_CONTEST,
|
||||
new WorldPoint(2626, 3415, 0), new WorldPoint(2631, 3425, 0),
|
||||
new WorldPoint(2629, 3435, 0), new WorldPoint(2636, 3444, 0)),
|
||||
FISHING_GUILD(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
|
||||
new WorldPoint(2604, 3423, 0), new WorldPoint(2605, 3417, 0),
|
||||
new WorldPoint(2611, 3413, 0)),
|
||||
FISHING_GUILD_PLATFORM(FishingSpot.MINNOW,
|
||||
new WorldPoint(2609, 3444, 0), new WorldPoint(2617, 3444, 0)),
|
||||
FISHING_PLATFORM(FishingSpot.SHRIMP,
|
||||
new WorldPoint(2788, 3273, 0), new WorldPoint(2794, 3279, 0),
|
||||
new WorldPoint(2793, 3283, 0)),
|
||||
HOSIDIUS_CENTER(FishingSpot.SALMON, new WorldPoint(1715, 3612, 0)),
|
||||
HOSIDIUS_EAST(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER, FishingSpot.SHRIMP},
|
||||
new WorldPoint(1817, 3603, 0), new WorldPoint(1827, 3605, 0),
|
||||
new WorldPoint(1828, 3614, 0), new WorldPoint(1840, 3619, 0),
|
||||
new WorldPoint(1838, 3595, 0)),
|
||||
INFIRMARY_SOUTH(FishingSpot.SALMON, new WorldPoint(1584, 3566, 0)),
|
||||
IORWERTH_CAMP_INSIDE(FishingSpot.SALMON, new WorldPoint(3239, 5997, 0)),
|
||||
IORWERTH_CAMP_NORTH_INSIDE(FishingSpot.SHARK, new WorldPoint(3185, 6027, 0)),
|
||||
IORWERTH_CAMP_NORTH_OUTSIDE(FishingSpot.SHARK, new WorldPoint(2161, 3275, 0)),
|
||||
IORWERTH_CAMP_OUTSIDE(FishingSpot.SALMON, new WorldPoint(2215, 3245, 0)),
|
||||
ISAFDAR_NORTH_EAST_INSIDE(FishingSpot.SALMON, new WorldPoint(3293, 6005, 0)),
|
||||
ISAFDAR_NORTH_EAST_OUTSIDE(FishingSpot.SALMON, new WorldPoint(2269, 3253, 0)),
|
||||
JATISZO(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
|
||||
new WorldPoint(2400, 3780, 0), new WorldPoint(2412, 3780, 0),
|
||||
new WorldPoint(2419, 3789, 0)),
|
||||
KINGSTOWN_EAST(FishingSpot.SALMON, new WorldPoint(1723, 3685, 0)),
|
||||
LANDS_END_EAST(FishingSpot.SHRIMP, new WorldPoint(1534, 3414, 0)),
|
||||
LANDS_END_WEST(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER, FishingSpot.SHRIMP},
|
||||
new WorldPoint(1484, 3432, 0)),
|
||||
LUMBRIDGE_RIVER(FishingSpot.SALMON,
|
||||
new WorldPoint(3238, 3241, 0), new WorldPoint(3237, 3253, 0)),
|
||||
LUMBRIDGE_SWAMP_CAVE_EAST(FishingSpot.CAVE_EEL, new WorldPoint(3244, 9570, 0)),
|
||||
LUMBRIDGE_SWAMP_CAVE_WEST(FishingSpot.CAVE_EEL, new WorldPoint(3153, 9544, 0)),
|
||||
LUMBRIDGE_SWAMP_SOUTH_EAST(FishingSpot.SHRIMP, new WorldPoint(3244, 3153, 0)),
|
||||
MARIM(FishingSpot.SHARK, new WorldPoint(2774, 2740, 0)),
|
||||
MOLCH_ISLAND(FishingSpot.COMMON_TENCH, new WorldPoint(1370, 3632, 0)),
|
||||
MORTTON(FishingSpot.SLIMY_EEL, new WorldPoint(3439, 3273, 0)),
|
||||
MORT_MYRE_SWAMP_NORTH(FishingSpot.SLIMY_EEL,
|
||||
new WorldPoint(3480, 3433, 0), new WorldPoint(3485, 3448, 0)),
|
||||
MORT_MYRE_SWAMP_WEST(FishingSpot.SLIMY_EEL,
|
||||
new WorldPoint(3425, 3409, 0), new WorldPoint(3432, 3415, 0)),
|
||||
MOR_UL_REK(FishingSpot.INFERNAL_EEL,
|
||||
new WorldPoint(2443, 5104, 0), new WorldPoint(2476, 5077, 0),
|
||||
new WorldPoint(2537, 5086, 0)),
|
||||
MOUNT_QUIDAMORTEM(FishingSpot.BARB_FISH,
|
||||
new WorldPoint(1271, 3546, 0), new WorldPoint(1265, 3541, 0),
|
||||
new WorldPoint(1253, 3542, 0)),
|
||||
MUDSKIPPER_POINT(FishingSpot.SHRIMP,
|
||||
new WorldPoint(2995, 3158, 0), new WorldPoint(2985, 3176, 0)),
|
||||
MUSA_POINT(new FishingSpot[]{FishingSpot.LOBSTER, FishingSpot.SHRIMP}, new WorldPoint(2925, 3179, 0)),
|
||||
MYTHS_GUILD_NORTH(FishingSpot.LOBSTER, new WorldPoint(2456, 2893, 0)),
|
||||
OBSERVATORY_EAST(FishingSpot.SALMON, new WorldPoint(2466, 3151, 0)),
|
||||
OTTOS_GROTTO(FishingSpot.BARB_FISH,
|
||||
new WorldPoint(2500, 3509, 0), new WorldPoint(2504, 3495, 0),
|
||||
new WorldPoint(2505, 3515, 0), new WorldPoint(2520, 3518, 0)),
|
||||
PISCATORIS(FishingSpot.MONKFISH, new WorldPoint(2308, 3700, 0)),
|
||||
PORT_PISCARILIUS_EAST(FishingSpot.ANGLERFISH, new WorldPoint(1831, 3773, 0)),
|
||||
PORT_PISCARILIUS_WEST(new FishingSpot[]{FishingSpot.LOBSTER, FishingSpot.SHRIMP},
|
||||
new WorldPoint(1762, 3796, 0), new WorldPoint(1745, 3802, 0)),
|
||||
PRIFFDINAS_INSIDE_EAST(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
|
||||
new WorldPoint(3186, 6102, 0), new WorldPoint(3187, 6123, 0)),
|
||||
PRIFFDINAS_INSIDE_NORTH(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
|
||||
new WorldPoint(3250, 6182, 0), new WorldPoint(3258, 6180, 0),
|
||||
new WorldPoint(3258, 6197, 0)),
|
||||
PRIFFDINAS_OUTSIDE_EAST(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
|
||||
new WorldPoint(2162, 3350, 0), new WorldPoint(2163, 3371, 0)),
|
||||
PRIFFDINAS_OUTSIDE_NORTH(new FishingSpot[]{FishingSpot.SHARK, FishingSpot.LOBSTER},
|
||||
new WorldPoint(2226, 3430, 0), new WorldPoint(2234, 3428, 0),
|
||||
new WorldPoint(2234, 3445, 0)),
|
||||
RELLEKKA_CENTER(FishingSpot.LOBSTER, new WorldPoint(2641, 3696, 0)),
|
||||
RELLEKKA_NORTH_EAST(FishingSpot.SHARK, new WorldPoint(2649, 3708, 0)),
|
||||
RELLEKKA_WEST(FishingSpot.SHRIMP, new WorldPoint(2632, 3694, 0)),
|
||||
RIVER_ARDOUGNE(FishingSpot.SALMON,
|
||||
new WorldPoint(2560, 3374, 0), new WorldPoint(2565, 3370, 0),
|
||||
new WorldPoint(2526, 3412, 0), new WorldPoint(2536, 3405, 0),
|
||||
new WorldPoint(2507, 3420, 0)),
|
||||
SAND_CRAB_PENINSULA_NORTH(FishingSpot.SHARK, new WorldPoint(1675, 3490, 0)),
|
||||
SAND_CRAB_PENINSULA_SOUTH(FishingSpot.SHRIMP, new WorldPoint(1676, 3469, 0)),
|
||||
SAND_CRAB_PENINSULA_WEST(FishingSpot.LOBSTER, new WorldPoint(1668, 3479, 0)),
|
||||
SEERS_VILLAGE(FishingSpot.SALMON,
|
||||
new WorldPoint(2725, 3524, 0), new WorldPoint(2714, 3531, 0)),
|
||||
SHILO_VILLAGE(FishingSpot.SALMON,
|
||||
new WorldPoint(2854, 2977, 0), new WorldPoint(2858, 2973, 0)),
|
||||
TAVERLEY_DUNGEON(FishingSpot.LAVA_EEL,
|
||||
new WorldPoint(2893, 9764, 0), new WorldPoint(2889, 9766, 0),
|
||||
new WorldPoint(2883, 9765, 0)),
|
||||
TREE_GNOME_STRONGHOLD(FishingSpot.SALMON,
|
||||
new WorldPoint(2389, 3422, 0), new WorldPoint(2382, 3415, 0)),
|
||||
TUTORIAL_ISLAND(FishingSpot.TUTORIAL_SHRIMP, new WorldPoint(3100, 3091, 0)),
|
||||
WATSON_HOUSE_SOUTH(FishingSpot.SALMON, new WorldPoint(1646, 3558, 0)),
|
||||
WILDERNESS_BANDIT_CAMP(FishingSpot.SHRIMP, new WorldPoint(3049, 3704, 0)),
|
||||
WILDERNESS_DARK_CRABS(FishingSpot.DARK_CRAB,
|
||||
new WorldPoint(3362, 3802, 0), new WorldPoint(3347, 3813, 0)),
|
||||
WILDERNESS_LAVA_MAZE(FishingSpot.LAVA_EEL, new WorldPoint(3071, 3840, 0)),
|
||||
WILDERNESS_RESOURCE_AREA(FishingSpot.DARK_CRAB, new WorldPoint(3186, 3925, 0)),
|
||||
ZUL_ANDRA(FishingSpot.SACRED_EEL,
|
||||
new WorldPoint(2183, 3068, 0), new WorldPoint(2195, 3067, 0)),
|
||||
;
|
||||
|
||||
private final WorldPoint[] locations;
|
||||
private final String tooltip;
|
||||
|
||||
FishingSpotLocation(FishingSpot fishingSpot, WorldPoint... locations)
|
||||
{
|
||||
this.tooltip = fishingSpot.getWorldMapTooltip();
|
||||
this.locations = locations;
|
||||
}
|
||||
|
||||
FishingSpotLocation(FishingSpot[] fishingSpot, WorldPoint... locations)
|
||||
{
|
||||
this.tooltip = Arrays.stream(fishingSpot).map(FishingSpot::getWorldMapTooltip).collect(Collectors.joining(" / "));
|
||||
this.locations = locations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020, melky <https://github.com/melkypie>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class FishingSpotPoint extends WorldMapPoint
|
||||
{
|
||||
FishingSpotPoint(WorldPoint point, String tooltip, BufferedImage icon)
|
||||
{
|
||||
super(point, icon);
|
||||
setTooltip(tooltip);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2020, melky <https://github.com/melkypie>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum HunterAreaLocation
|
||||
{
|
||||
BONEYARD_HUNTER_AREA(new WorldPoint(3294, 3673, 0), HunterCreature.BLACK_SALAMANDER),
|
||||
CANIFIS_HUNTER_AREA1(new WorldPoint(3553, 3438, 0), HunterCreature.SWAMP_LIZARD),
|
||||
CANIFIS_HUNTER_AREA2(new WorldPoint(3535, 3445, 0), HunterCreature.SWAMP_LIZARD),
|
||||
FALCONRY(new WorldPoint(2379, 3599, 0), HunterCreature.SPOTTED_KEBBIT, HunterCreature.DARK_KEBBIT,
|
||||
HunterCreature.DASHING_KEBBIT, HunterCreature.GREATER_SIREN),
|
||||
FELDIP_HUNTER_AREA(new WorldPoint(2557, 2912, 0), HunterCreature.CRIMSON_SWIFT, HunterCreature.FELDIP_WEASEL,
|
||||
HunterCreature.TROPICAL_WAGTAIL, HunterCreature.SPINED_LARUPIA, HunterCreature.BARB_TAILED_KEBBIT,
|
||||
HunterCreature.BLACK_WARLOCK, HunterCreature.CARNIVOROUS_CHINCHOMPA),
|
||||
FOSSIL_ISLAND1(new WorldPoint(3693, 3800, 0), HunterCreature.HERBIBOAR),
|
||||
FOSSIL_ISLAND2(new WorldPoint(3701, 3809, 0), HunterCreature.HERBIBOAR),
|
||||
FOSSIL_ISLAND3(new WorldPoint(3703, 3829, 0), HunterCreature.HERBIBOAR),
|
||||
FOSSIL_ISLAND4(new WorldPoint(3749, 3850, 0), HunterCreature.HERBIBOAR),
|
||||
FOSSIL_ISLAND5(new WorldPoint(3684, 3870, 0), HunterCreature.HERBIBOAR),
|
||||
FOSSIL_ISLAND_UNDERWATER(new WorldPoint(3743, 10295, 0), HunterCreature.FISH_SHOAL),
|
||||
GWENITH_HUNTER_AREA_OUTSIDE(new WorldPoint(2269, 3408, 0), HunterCreature.CARNIVOROUS_CHINCHOMPA),
|
||||
GWENITH_HUNTER_AREA_INSIDE(new WorldPoint(3293, 6160, 0), HunterCreature.CARNIVOROUS_CHINCHOMPA),
|
||||
KARAMJA_HUNTER_AREA(new WorldPoint(2786, 3001, 0), HunterCreature.HORNED_GRAAHK),
|
||||
KEBOS_SWAMP(new WorldPoint(1184, 3595, 0), HunterCreature.CRIMSON_SWIFT),
|
||||
KOUREND_WOODLAND_CENTER(new WorldPoint(1512, 3478, 0), HunterCreature.RUBY_HARVEST),
|
||||
KOUREND_WOODLAND_NORTH_WEST(new WorldPoint(1481, 3504, 0), HunterCreature.CHINCHOMPA),
|
||||
KOUREND_WOODLAND_SOUTH(new WorldPoint(1556, 3436, 0), HunterCreature.COPPER_LONGTAIL),
|
||||
LAKE_MOLCH(new WorldPoint(1363, 3632, 0), HunterCreature.BLUEGILL, HunterCreature.COMMON_TENCH,
|
||||
HunterCreature.MOTTLED_EEL, HunterCreature.GREATER_SIREN),
|
||||
OURANIA_HUNTER_AREA_EAST(new WorldPoint(2447, 3219, 0), HunterCreature.RED_SALAMANDER),
|
||||
OURANIA_HUNTER_AREA_SOUTH(new WorldPoint(2475, 3240, 0), HunterCreature.RED_SALAMANDER),
|
||||
PISCATORIS_HUNTER_AREA(new WorldPoint(2335, 3584, 0), HunterCreature.COMMON_KEBBIT, HunterCreature.COPPER_LONGTAIL,
|
||||
HunterCreature.RUBY_HARVEST, HunterCreature.WILD_KEBBIT, HunterCreature.FERRET, HunterCreature.WHITE_RABBIT,
|
||||
HunterCreature.PRICKLY_KEBBIT, HunterCreature.RAZOR_BACKED_KEBBIT, HunterCreature.CHINCHOMPA),
|
||||
RELLEKA_HUNTER_AREA(new WorldPoint(2719, 3780, 0), HunterCreature.POLAR_KEBBIT, HunterCreature.CERULEAN_TWITCH,
|
||||
HunterCreature.SAPPHIRE_GLACIALIS, HunterCreature.SNOWY_KNIGHT,
|
||||
HunterCreature.SABRE_TOOTHED_KEBBIT, HunterCreature.SABRE_TOOTHED_KYATT),
|
||||
SLEPE_NORTH(new WorldPoint(3677, 3405, 0), HunterCreature.SWAMP_LIZARD),
|
||||
UZER_HUNTER_AREA(new WorldPoint(3401, 3104, 0), HunterCreature.GOLDEN_WARBLER, HunterCreature.DESERT_DEVIL,
|
||||
HunterCreature.ORANGE_SALAMANDER),
|
||||
WILDERNESS(new WorldPoint(3142, 3771, 0), HunterCreature.BLACK_CHINCHOMPA),
|
||||
;
|
||||
|
||||
private final WorldPoint location;
|
||||
private final String tooltip;
|
||||
|
||||
HunterAreaLocation(WorldPoint location, HunterCreature... creatures)
|
||||
{
|
||||
this.location = location;
|
||||
this.tooltip = Joiner.on("<br>").join(creatures);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private enum HunterCreature
|
||||
{
|
||||
BARB_TAILED_KEBBIT("Barb-tailed kebbit", 33),
|
||||
BLACK_CHINCHOMPA("Black chinchompa", 73),
|
||||
BLACK_SALAMANDER("Black salamander", 67),
|
||||
BLACK_WARLOCK("Black warlock", 45),
|
||||
BLUEGILL("Bluegill", 35),
|
||||
CARNIVOROUS_CHINCHOMPA("Carnivorous chinchompa", 63),
|
||||
CERULEAN_TWITCH("Cerulean twitch", 11),
|
||||
CHINCHOMPA("Chinchompa", 53),
|
||||
COMMON_KEBBIT("Common kebbit", 3),
|
||||
COMMON_TENCH("Common tench", 51),
|
||||
COPPER_LONGTAIL("Copper longtail", 9),
|
||||
CRIMSON_SWIFT("Crimson swift", 1),
|
||||
DARK_KEBBIT("Dark kebbit", 57),
|
||||
DASHING_KEBBIT("Dashing kebbit", 69),
|
||||
DESERT_DEVIL("Desert devil", 13),
|
||||
FELDIP_WEASEL("Feldip Weasel", 7),
|
||||
FERRET("Ferret", 27),
|
||||
FISH_SHOAL("Fish shoal", 44),
|
||||
GOLDEN_WARBLER("Golden warbler", 5),
|
||||
GREATER_SIREN("Greater siren", 87),
|
||||
HERBIBOAR("Herbiboar", 80),
|
||||
HORNED_GRAAHK("Horned graahk", 41),
|
||||
// IMP and MANIACAL_MONKEY do not have a specific hunter area
|
||||
MOTTLED_EEL("Mottled eel", 68),
|
||||
ORANGE_SALAMANDER("Orange salamander", 47),
|
||||
POLAR_KEBBIT("Polar kebbit", 1),
|
||||
PRICKLY_KEBBIT("Prickly kebbit", 37),
|
||||
RAZOR_BACKED_KEBBIT("Razor-backed kebbit", 49),
|
||||
RED_SALAMANDER("Red salamander", 59),
|
||||
RUBY_HARVEST("Ruby harvest", 15),
|
||||
SABRE_TOOTHED_KEBBIT("Sabre-toothed kebbit", 51),
|
||||
SABRE_TOOTHED_KYATT("Sabre-toothed kyatt", 55),
|
||||
SAPPHIRE_GLACIALIS("Sapphire glacialis", 25),
|
||||
SNOWY_KNIGHT("Snowy knight", 35),
|
||||
SPINED_LARUPIA("Spined larupia", 31),
|
||||
SPOTTED_KEBBIT("Spotted kebbit", 43),
|
||||
SWAMP_LIZARD("Swamp lizard", 29),
|
||||
TROPICAL_WAGTAIL("Tropical wagtail", 19),
|
||||
WHITE_RABBIT("White rabbit", 27),
|
||||
WILD_KEBBIT("Wild kebbit", 23),
|
||||
;
|
||||
|
||||
private String name;
|
||||
private int level;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name + " (" + level + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020, melky <https://github.com/melkypie>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class HunterAreaPoint extends WorldMapPoint
|
||||
{
|
||||
HunterAreaPoint(HunterAreaLocation data, BufferedImage icon)
|
||||
{
|
||||
super(data.getLocation(), icon);
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Brooklyn <https://github.com/Broooklyn>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum KourendTaskLocation
|
||||
{
|
||||
ARCEUUS_LIBRARY_SOUTH("Arceuus Task (0%) - Library Assistance", new WorldPoint(1622, 3801, 0)),
|
||||
ARCEUUS_LIBRARY_NORTH("Arceuus Task (0%) - Library Assistance", new WorldPoint(1638, 3817, 0)),
|
||||
ARCEUUS_DENSE_ESSENCE("Arceuus Task (25%) - Dense Essence Mining", new WorldPoint(1757, 3852, 0)),
|
||||
ARCEUUS_REANIMATE_CREATURES("Arceuus Task (60%) - Creature Reanimation", new WorldPoint(1714, 3883, 0)),
|
||||
ARCEUUS_BLOOD_ALTAR("Arceuus Unlock (100%) - Blood Rune Crafting", new WorldPoint(1716, 3829, 0)),
|
||||
ARCEUUS_SOUL_ALTAR("Arceuus Unlock (100%) - Soul Rune Crafting", new WorldPoint(1814, 3854, 0)),
|
||||
|
||||
HOSIDIUS_PLOUGH_NORTH("Hosidius Task (0%) - Ploughs", new WorldPoint(1770, 3550, 0)),
|
||||
HOSIDIUS_PLOUGH_SOUTH("Hosidius Task (0%) - Ploughs", new WorldPoint(1769, 3528, 0)),
|
||||
HOSIDUIS_FERTILISER("Hosidius Task (5%) - Making Fertilizer", new WorldPoint(1701, 3527, 0)),
|
||||
HOSIDIUS_SPIRIT_TREE("Hosidius Unlock (35%) - Spirit Tree Patch", new WorldPoint(1695, 3545, 0)),
|
||||
HOSIDIUS_MESS("Hosidius Task (45%) - Mess", new WorldPoint(1639, 3629, 0)),
|
||||
HOSIDIUS_FARMING_PATCH("Hosidius Unlock (50%) - Disease Protection", new WorldPoint(1740, 3552, 0)),
|
||||
HOSIDIUS_VINERY("Hosidius Task (65%) - Grape Planting", new WorldPoint(1804, 3564, 0)),
|
||||
HOSIDIUS_TITHE_FARM("Hosidius Unlock (100%) - Tithe Farm", new WorldPoint(1802, 3499, 0)),
|
||||
HOSIDIUS_KITCHEN("Hosidius Unlock (100%) - Kitchen", new WorldPoint(1678, 3618, 0)),
|
||||
|
||||
LOVAKENGJ_DYNAMITE("Lovakengj Task (0%) - Making Juniper Charcoal", new WorldPoint(1718, 3472, 0)),
|
||||
LOVAKENGJ_SULFUR("Lovakengj Task (0%) - Mining Volcanic Sulphur", new WorldPoint(1437, 3861, 0)),
|
||||
LOVAKENGJ_ARMOURER_T1("Lovakengj Task (30%) - Armourer (Tier 1)", new WorldPoint(1453, 3750, 0)),
|
||||
LOVAKENGJ_ARMOURER_T2("Lovakengj Task (40%) - Armourer (Tier 2)", new WorldPoint(1436, 3784, 0)),
|
||||
LOVAKENGJ_ARMOURER_T3("Lovakengj Task (50%) - Armourer (Tier 3)", new WorldPoint(1430, 3797, 0)),
|
||||
LOVAKENGJ_ARMOURER_T4("Lovakengj Task (60%) - Armourer (Tier 4)", new WorldPoint(1460, 3763, 0)),
|
||||
LOVAKENGJ_ARMOURER_T5("Lovakengj Task (70%) - Armourer (Tier 5)", new WorldPoint(1524, 3755, 0)),
|
||||
LOVAKENGJ_BLAST_MINE("Lovakengj Unlock (100%) - Blast Mine", new WorldPoint(1488, 3865, 0)),
|
||||
|
||||
PISCARILIUS_CRANE_REPAIR("Piscarilius Task (0%) - Fishing Crane Repair", new WorldPoint(1820, 3742, 0)),
|
||||
PISCARILIUS_FRESH_FISH("Piscarilius Task (15%) - Fish Delivery", new WorldPoint(1831, 3716, 0)),
|
||||
PISCARILIUS_SANDWORMS("Piscarilius Task (30%) - Hunting Sandworms", new WorldPoint(1841, 3789, 0)),
|
||||
PISCARILIUS_STEALING_ARTEFACTS("Piscarilius Task (75%) - Stealing Artefacts", new WorldPoint(1849, 3753, 0)),
|
||||
|
||||
SHAYZIEN_HEALING_SOLDIERS("Shayzien Task (0%) - Healing Wounded Soldiers", new WorldPoint(1572, 3581, 0)),
|
||||
SHAYZIEN_LIZARDMEN_EAST("Shayzien Task (5%) - Killing Lizardmen", new WorldPoint(1570, 3668, 0)),
|
||||
SHAYZIEN_LIZARDMEN_WEST("Shayzien Task (5%) - Killing Lizardmen", new WorldPoint(1471, 3686, 0)),
|
||||
SHAYZIEN_ORGANIZED_CRIME("Shayzien Task (40%) - Organized Crime", new WorldPoint(1565, 3605, 0)),
|
||||
SHAYZIEN_COMBAT_RING("Shayzien Task (60%) - Combat Ring", new WorldPoint(1539, 3589, 0)),
|
||||
SHAYZIEN_LIZARDMAN_SHAMANS("Shayzien Unlock (100%) - Lizardman Shamans", new WorldPoint(1455, 3693, 0));
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
|
||||
KourendTaskLocation(String tooltip, WorldPoint location)
|
||||
{
|
||||
this.tooltip = tooltip;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Brooklyn <https://github.com/Broooklyn>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
public class KourendTaskPoint extends WorldMapPoint
|
||||
{
|
||||
KourendTaskPoint(KourendTaskLocation data)
|
||||
{
|
||||
super(data.getLocation(), WorldMapPlugin.BLANK_ICON);
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Magic fTail
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum MinigameLocation
|
||||
{
|
||||
BARBARIAN_ASSAULT("Barbarian Assault", new WorldPoint(2531, 3569, 0)),
|
||||
BURGH_DE_ROTT_RAMBLE("Burgh de Rott Ramble", new WorldPoint(3434, 3487, 0)),
|
||||
CASTLE_WARS("Castle Wars", new WorldPoint(2439, 3092, 0)),
|
||||
CASTLE_WARS_PORTAL("Castle Wars Portal", new WorldPoint(3140, 3626, 0)),
|
||||
DUEL_ARENA("Duel Arena", new WorldPoint(3313, 3238, 0)),
|
||||
MAGE_ARENA("Mage Arena", new WorldPoint(3095, 3957, 0)),
|
||||
NIGHTMARE_ZONE("Nightmare Zone", new WorldPoint(2606, 3115, 0)),
|
||||
PEST_CONTROL_NOVICE("Pest Control Novice", new WorldPoint(2660, 2637, 0)),
|
||||
PEST_CONTROL_INTERMEDIATE("Pest Control Intermediate", new WorldPoint(2638, 2641, 0)),
|
||||
PEST_CONTROL_VETERAN("Pest Control Veteran", new WorldPoint(2632, 2648, 0)),
|
||||
TEMPLE_TREKKING("Temple Trekking", new WorldPoint(3479, 3240, 0)),
|
||||
TZHAAR_FIGHT_CAVE("TzHaar Fight Cave", new WorldPoint(2437, 5168, 0)),
|
||||
TZHAAR_FIGHT_PIT("TzHaar Fight Pit", new WorldPoint(2398, 5177, 0)),
|
||||
LAST_MAN_STANDING("Last Man Standing", new WorldPoint(3138, 3635, 0)),
|
||||
INFERNO("Inferno", new WorldPoint(2495, 5118, 0)),
|
||||
BRIMHAVEN_AGILITY_ARENA("Brimhaven Agility Arena", new WorldPoint(2809, 3191, 0)),
|
||||
FISHING_TRAWLER("Fishing Trawler", new WorldPoint(2667, 3163, 0)),
|
||||
GNOME_BALL("Gnome Ball", new WorldPoint(2381, 3488, 0)),
|
||||
GNOME_RESTAURANT("Gnome Restaurant", new WorldPoint(2436, 3502, 0)),
|
||||
IMPETUOUS_IMPULSES("Impetuous Impulses", new WorldPoint(2425, 4445, 0)),
|
||||
MAGE_TRAINING_ARENA("Mage Training Arena", new WorldPoint(3362, 3318, 0)),
|
||||
PYRAMID_PLUNDER("Pyramid Plunder", new WorldPoint(3288, 2787, 0)),
|
||||
RANGING_GUILD("Ranging Guild", new WorldPoint(2671, 3419, 0)),
|
||||
ROGUES_DEN("Rogues' Den", new WorldPoint(2905, 3537, 0)),
|
||||
SORCERESSS_GARDEN("Sorceress's Garden", new WorldPoint(3285, 3180, 0)),
|
||||
TROUBLE_BREWING("Trouble Brewing", new WorldPoint(3811, 3021, 0)),
|
||||
VOLCANIC_MINE("Volcanic Mine", new WorldPoint(3812, 3810, 0)),
|
||||
TAI_BWO_WANNAI_CLEANUP("Tai Bwo Wannai Cleanup", new WorldPoint(2795, 3066, 0)),
|
||||
BURTHORPE_GAMES_ROOM("Burthorpe Games Room", new WorldPoint(2900, 3565, 0)),
|
||||
RAT_PITS_PORT_SARIM("Rat Pits", new WorldPoint(3015, 3232, 0)),
|
||||
RAT_PITS_VARROCK("Rat Pits", new WorldPoint(3266, 3400, 0)),
|
||||
RAT_PITS_ARDOUGNE("Rat Pits", new WorldPoint(2561, 3318, 0)),
|
||||
RAT_PITS_KELDAGRIM("Rat Pits", new WorldPoint(2913, 10188, 0)),
|
||||
TEARS_OF_GUTHIX("Tears of Guthix", new WorldPoint(3257, 9517, 0)),
|
||||
CLAN_WARS("Clan Wars", new WorldPoint(3133, 3621, 0)),
|
||||
ANIMATION_ROOM("Animation Room", new WorldPoint(2853, 3537, 0)),
|
||||
DUMMY_ROOM("Dummy Room", new WorldPoint(2857, 3551, 0)),
|
||||
CATAPULT_ROOM("Catapult Room", new WorldPoint(2842, 3545, 0)),
|
||||
SHOT_PUT_ROOM("Shot Put Room", new WorldPoint(2863, 3550, 0)),
|
||||
HALLOWED_SEPULCHRE("Hallowed Sepulchre", new WorldPoint(3653, 3386, 1)),
|
||||
THE_GAUNTLET("The Gauntlet", new WorldPoint(3223, 12505, 1));
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
|
||||
MinigameLocation(String tooltip, WorldPoint location)
|
||||
{
|
||||
this.tooltip = tooltip;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Magic fTail
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class MinigamePoint extends WorldMapPoint
|
||||
{
|
||||
MinigamePoint(MinigameLocation data, BufferedImage icon)
|
||||
{
|
||||
super(data.getLocation(), icon);
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2020, dekvall <https://github.com/dekvall>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum MiningSiteLocation
|
||||
{
|
||||
AGILITY_PYRAMID(new WorldPoint(3322, 2875, 0), new Rock(5, Ore.GOLD)),
|
||||
// ABANDONED_MINE -- NOT AVAILABLE ON WORLDMAP
|
||||
AL_KHARID_MINE_NORTH(new WorldPoint(3298, 3312, 0),
|
||||
new Rock(3, Ore.COPPER), new Rock(1, Ore.TIN), new Rock(7, Ore.IRON), new Rock(5, Ore.SILVER),
|
||||
new Rock(3, Ore.COAL), new Rock(3, Ore.MITHRIL), new Rock(2, Ore.ADAMANTITE)),
|
||||
AL_KHARID_MINE_SOUTH(new WorldPoint(3298, 3282, 0), new Rock(2, Ore.IRON), new Rock(2, Ore.GOLD)),
|
||||
ARANDAR(new WorldPoint(2322, 3269, 0), new Rock(8, Ore.LIMESTONE)),
|
||||
ARANDAR_PRIFDDINAS_MAP(new WorldPoint(3346, 6021, 0), new Rock(8, Ore.LIMESTONE)),
|
||||
ARCEUUS_NORTH(new WorldPoint(1763, 3860, 0), new Rock(1, Ore.DENSE_ESSENCE)),
|
||||
ARCEUUS_SOUTH(new WorldPoint(1763, 3844, 0), new Rock(1, Ore.DENSE_ESSENCE)),
|
||||
ARDOUGNE_SEWERS(new WorldPoint(2670, 9680, 0), new Rock(5, Ore.IRON), new Rock(5, Ore.COAL)),
|
||||
ARDOUGNE_SOUTH_EAST(new WorldPoint(2599, 3232, 0), new Rock(6, Ore.IRON), new Rock(4, Ore.COAL)),
|
||||
// ARZINIAN_MINE -- NOT AVAILABLE ON WORLD MAP
|
||||
ASGARNIA_ICE_DUNGEON_EAST(new WorldPoint(3063, 9582, 0), new Rock(2, Ore.BLURITE)),
|
||||
ASGARNIA_ICE_DUNGEON_WEST(new WorldPoint(3049, 9568, 0), new Rock(2, Ore.BLURITE)),
|
||||
BANDIT_CAMP_MINE(new WorldPoint(3086, 3763, 0), new Rock(16, Ore.IRON), new Rock(20, Ore.COAL), new Rock(22, Ore.MITHRIL), new Rock(8, Ore.ADAMANTITE)),
|
||||
BANDIT_CAMP_QUARRY(new WorldPoint(3171, 2912, 0), new Rock(4, Ore.CLAY), new Rock(2, Ore.COAL), new Rock(32, Ore.SANDSTONE), new Rock(28, Ore.GRANITE)),
|
||||
BARBARIAN_VILLAGE(new WorldPoint(3078, 3421, 0), new Rock(5, Ore.TIN), new Rock(4, Ore.COAL)),
|
||||
BATTLEFIELD(new WorldPoint(2471, 3255, 0), new Rock(2, Ore.COPPER), new Rock(1, Ore.TIN)),
|
||||
BLAST_MINE_EAST(new WorldPoint(1502, 3869, 0), new Rock(20, Ore.HARD_ROCK)),
|
||||
BLAST_MINE_NORTH(new WorldPoint(1485, 3882, 0), new Rock(17, Ore.HARD_ROCK)),
|
||||
BLAST_MINE_WEST(new WorldPoint(1471, 3865, 0), new Rock(22, Ore.HARD_ROCK)),
|
||||
BRIMHAVEN_NORTH(new WorldPoint(2732, 3225, 0), new Rock(10, Ore.GOLD)),
|
||||
BRIMHAVEN_SOUTH_(new WorldPoint(2743, 3150, 0), new Rock(6, Ore.GOLD)),
|
||||
CENTRAL_FREMENIK_ISLES(new WorldPoint(2374, 3850, 0), new Rock(7, Ore.COAL), new Rock(1, Ore.RUNITE)),
|
||||
CITHAREDE_ABBEY(new WorldPoint(3400, 3170, 0), new Rock(3, Ore.IRON), new Rock (3, Ore.COAL)),
|
||||
COAL_TRUCKS(new WorldPoint(2580, 3484, 0), new Rock(18, Ore.COAL)),
|
||||
CRAFTING_GUILD(new WorldPoint(2939, 3283, 0), new Rock(6, Ore.CLAY), new Rock(6, Ore.SILVER), new Rock(7, Ore.GOLD)),
|
||||
CRANDOR_NORTH_EAST(new WorldPoint(2860, 3287, 0), new Rock(3, Ore.GOLD)),
|
||||
CRANDOR_NORTH_WEST(new WorldPoint(2831, 3296, 0), new Rock(7, Ore.COAL), new Rock(1, Ore.MITHRIL)),
|
||||
CRANDOR_SOUTH_EAST(new WorldPoint(2835, 3245, 0), new Rock(3, Ore.COAL), new Rock(3, Ore.ADAMANTITE)),
|
||||
CRANDOR_SOUTH_WEST(new WorldPoint(2819, 3247, 0), new Rock(7, Ore.MITHRIL)),
|
||||
DAEYALT_ESSENCE_MINE(new WorldPoint(3631, 3340, 0), new Rock(3, Ore.DAEYALT_ESSENCE)),
|
||||
DESERT_MINING_CAMP_SURFACE(new WorldPoint(3299, 3021, 0), true, new Rock(4, Ore.COPPER), new Rock(4, Ore.TIN), new Rock(3, Ore.IRON), new Rock(4, Ore.COAL)),
|
||||
// DESERT_MINING_CAMP_UNDERGROUND -- NOT AVAILABLE ON WORLDMAP
|
||||
DORGESH_KAAN_NORTH(new WorldPoint(3309, 9645, 0), new Rock(1, Ore.IRON), new Rock(9, Ore.SILVER)),
|
||||
DORGESH_KAAN_SOUTH_EAST(new WorldPoint(3322, 9616, 0), new Rock(3, Ore.IRON)),
|
||||
DORGESH_KAAN_SOUTH_WEST(new WorldPoint(3312, 9621, 0), new Rock(3, Ore.IRON)),
|
||||
DORGESH_KAAN_WEST(new WorldPoint(3311, 9628, 0), new Rock(3, Ore.IRON), new Rock(2, Ore.SILVER)),
|
||||
DWARVEN_EAST_BOTTOM(new WorldPoint(3039, 9763, 0),
|
||||
new Rock(5, Ore.TIN), new Rock(2, Ore.IRON), new Rock(8, Ore.COAL), new Rock(2, Ore.GOLD), new Rock(1, Ore.ADAMANTITE)),
|
||||
DWARVEN_EAST_MIDDLE(new WorldPoint(3037, 9775, 0),
|
||||
new Rock(4, Ore.COPPER), new Rock(3, Ore.IRON), new Rock(3, Ore.COAL), new Rock(2, Ore.MITHRIL), new Rock(2, Ore.ADAMANTITE)),
|
||||
DWARVEN_EAST_TOP(new WorldPoint(3051, 9820, 0), new Rock(2, Ore.CLAY), new Rock(3, Ore.TIN), new Rock(2, Ore.IRON)),
|
||||
DWARVEN_WEST_BOTTOM(new WorldPoint(3028, 9809, 0), new Rock(3, Ore.CLAY), new Rock(4, Ore.COPPER)),
|
||||
DWARVEN_WEST_TOP(new WorldPoint(3031, 9828, 0), new Rock(3, Ore.COPPER), new Rock(2, Ore.TIN), new Rock(2, Ore.IRON)),
|
||||
FREMENIK_ISLES_EAST(new WorldPoint(2405, 3867, 0), new Rock(3, Ore.COPPER), new Rock(3, Ore.TIN), new Rock(4, Ore.COAL)),
|
||||
EAGLES_OUTPOST(new WorldPoint(3424, 3164, 0), new Rock(7, Ore.CLAY)),
|
||||
EDGEVILLE_DUNGEON(new WorldPoint(3138, 9874, 0),
|
||||
new Rock(2, Ore.COPPER), new Rock(2, Ore.TIN), new Rock(3, Ore.IRON), new Rock(3, Ore.SILVER),
|
||||
new Rock(6, Ore.COAL), new Rock(1, Ore.MITHRIL), new Rock(2, Ore.ADAMANTITE)),
|
||||
// EVIL_CHICKEN_LAIR -- NOT AVAILABLE ON WORLD MAP
|
||||
FALADOR_WEST(new WorldPoint(2907, 3362, 0),
|
||||
new Rock(2, Ore.COPPER), new Rock(6, Ore.TIN), new Rock(3, Ore.IRON), new Rock(2, Ore.COAL)),
|
||||
FELDIP_HILLS_EAST(new WorldPoint(2638, 2996, 0), new Rock(3, Ore.ROCK)),
|
||||
FELDIP_HILLS_MIDDLE(new WorldPoint(2579, 2998, 0), new Rock(4, Ore.ROCK)),
|
||||
FELDIP_HILLS_WEST(new WorldPoint(2567, 2961, 0), new Rock(3, Ore.ROCK)),
|
||||
FIGHT_ARENA(new WorldPoint(2630, 3142, 0),
|
||||
new Rock(4, Ore.CLAY), new Rock(2, Ore.COPPER), new Rock(7, Ore.TIN), new Rock(9, Ore.IRON),
|
||||
new Rock(1, Ore.COAL), new Rock(2, Ore.MITHRIL)),
|
||||
FOSSIL_ISLAND(new WorldPoint(3770, 3815, 0),
|
||||
new Rock(7, Ore.IRON), new Rock(20, Ore.COAL), new Rock(3, Ore.MITHRIL), new Rock(5, Ore.ADAMANTITE),
|
||||
new Rock(2, Ore.RUNITE)),
|
||||
FREMENNIK_ISLES_WEST(new WorldPoint(2310, 3853, 0), new Rock(3, Ore.COPPER)),
|
||||
FROZEN_WASTE_PLATEU_CENTER(new WorldPoint(2963, 3933, 0), new Rock(1, Ore.RUNITE)),
|
||||
FROZEN_WASTE_PLATEU_NORTH(new WorldPoint(2975, 3937, 0), new Rock(1, Ore.RUNITE)),
|
||||
FROZEN_WASTE_PLATEU_SOUTH(new WorldPoint(2947, 3914, 0), new Rock(1, Ore.RUNITE)),
|
||||
GRAND_TREE(new WorldPoint(2489, 9916, 0),
|
||||
new Rock(9, Ore.CLAY), new Rock(8, Ore.IRON), new Rock(4, Ore.SILVER), new Rock(11, Ore.COAL),
|
||||
new Rock(4, Ore.GOLD), new Rock(4, Ore.MITHRIL), new Rock(3, Ore.ADAMANTITE)),
|
||||
GWENITH(new WorldPoint(2163, 3415, 0), new Rock(10, Ore.GOLD)),
|
||||
GWENITH_PRIFDDINAS_MAP(new WorldPoint(3187, 6167, 0), new Rock(10, Ore.GOLD)),
|
||||
HEROES_GUILD_EAST_BOTTOM(new WorldPoint(2939, 9898, 0), new Rock(3, Ore.COAL), new Rock(2, Ore.RUNITE)),
|
||||
HEROES_GUILD_EAST_TOP(new WorldPoint(2940, 9884, 0), new Rock(5, Ore.COAL)),
|
||||
HEROES_GUILD_WEST_BOTTOM(new WorldPoint(2921, 9904, 0), new Rock(3, Ore.COAL)),
|
||||
HEROES_GUILD_WEST_TOP(new WorldPoint(2914, 9916, 0), new Rock(2, Ore.MITHRIL), new Rock(2, Ore.ADAMANTITE)),
|
||||
HOSIDIUS_MINE(new WorldPoint(1777, 3489, 0),
|
||||
new Rock(10, Ore.CLAY), new Rock(11, Ore.COPPER), new Rock(4, Ore.TIN), new Rock(9, Ore.IRON),
|
||||
new Rock(2, Ore.SILVER)),
|
||||
ISAFDAR(new WorldPoint(2277, 3159, 0), new Rock(4, Ore.ADAMANTITE), new Rock(2, Ore.RUNITE)),
|
||||
JATIZSO(new WorldPoint(2396, 3812, 0),
|
||||
new Rock(11, Ore.TIN), new Rock(7, Ore.IRON), new Rock(8, Ore.COAL), new Rock(15, Ore.MITHRIL),
|
||||
new Rock(11, Ore.ADAMANTITE)),
|
||||
KARAMJA_JUNGLE(new WorldPoint(2848, 3033, 0),
|
||||
new Rock(1, Ore.IRON), new Rock(1, Ore.SILVER), new Rock(1, Ore.COAL), new Rock(2, Ore.MITHRIL),
|
||||
new Rock(2, Ore.ADAMANTITE)),
|
||||
KARAMJA_VOLCANO(new WorldPoint(2856, 9579, 0), new Rock(4, Ore.GOLD)),
|
||||
KEBOS_LOWLANDS(new WorldPoint(1211, 3657, 0), new Rock(4, Ore.ADAMANTITE), new Rock(5, Ore.MITHRIL)),
|
||||
KELDAGRIM_ENTRANCE(new WorldPoint(2724, 3693, 0), new Rock(9, Ore.IRON), new Rock(2, Ore.MITHRIL)),
|
||||
KELDAGRIM_NORTH_EAST(new WorldPoint(2937, 10232, 0), new Rock(9, Ore.COAL)),
|
||||
KELDAGRIM_SOUTH_WEST_BOTTOM(new WorldPoint(2872, 10119, 0), new Rock(2, Ore.COPPER), new Rock(5, Ore.COAL)),
|
||||
KELDAGRIM_SOUTH_WEST_MIDDLE(new WorldPoint(2818, 10156, 0), new Rock(4, Ore.IRON), new Rock(1, Ore.GOLD)),
|
||||
KELDAGRIM_SOUTH_WEST_TOP(new WorldPoint(2864, 10170, 0), new Rock(5, Ore.TIN)),
|
||||
LAVA_MAZE_DUNGEON(new WorldPoint(3045, 10263, 0), true, new Rock(1, Ore.RUNITE)),
|
||||
LAVA_MAZE_NORTH(new WorldPoint(3059, 3884, 0), new Rock(2, Ore.RUNITE)),
|
||||
LEGENDS_GUILD_EAST(new WorldPoint(2709, 3331, 0), new Rock(6, Ore.IRON), new Rock(8, Ore.COAL)),
|
||||
LEGENDS_GUILD_WEST(new WorldPoint(2694, 3332, 0), new Rock(5, Ore.IRON), new Rock(5, Ore.COAL)),
|
||||
LOVAKENGJ_SOUTH(new WorldPoint(1476, 3779, 0), new Rock(4, Ore.IRON), new Rock(6, Ore.COAL), new Rock(1, Ore.MITHRIL)),
|
||||
LOVAKENGJ_SULPHUR_EAST(new WorldPoint(1445, 3870, 0), new Rock(3, Ore.VOLCANIC_SULPHUR)),
|
||||
LOVAKENGJ_SULPHUR_WEST(new WorldPoint(1427, 3870, 0), new Rock(2, Ore.VOLCANIC_SULPHUR)),
|
||||
LOVAKENGJ_WEST(new WorldPoint(1432, 3845, 0), true, new Rock(45, Ore.COAL), new Rock(80, Ore.LOVAKITE)),
|
||||
LUMBRIDGE_SWAMP_EAST(new WorldPoint(3226, 3146, 0), new Rock(5, Ore.COPPER), new Rock(5, Ore.TIN)),
|
||||
LUMBRIDGE_SWAMP_WEST(new WorldPoint(3148, 3149, 0),
|
||||
new Rock(7, Ore.COAL), new Rock(5, Ore.MITHRIL), new Rock(2, Ore.ADAMANTITE)),
|
||||
// Lunar Isle Dungeon: Starting north-east and going clockwise
|
||||
LUNAR_ISLE_1(new WorldPoint(2163, 10347, 0),
|
||||
new Rock(2, Ore.SILVER), new Rock(1, Ore.GOLD), new Rock(1, Ore.GEM_ROCK), new Rock(6, Ore.LUNAR)),
|
||||
LUNAR_ISLE_2(new WorldPoint(2165, 10325, 0), new Rock(3, Ore.GEM_ROCK), new Rock(4, Ore.LUNAR)),
|
||||
LUNAR_ISLE_3(new WorldPoint(2140, 10318, 0), new Rock(3, Ore.SILVER), new Rock(3, Ore.LUNAR)),
|
||||
LUNAR_ISLE_4(new WorldPoint(2125, 10327, 0), new Rock(4, Ore.GOLD), new Rock(1, Ore.LUNAR)),
|
||||
LUNAR_ISLE_5(new WorldPoint(2124, 10342, 0), new Rock(2, Ore.GOLD), new Rock(5, Ore.LUNAR)),
|
||||
MINING_GUILD_AMETHYST(new WorldPoint(3022, 9704, 0), new Rock(26, Ore.AMETHYST)),
|
||||
MINING_GUILD_NORTH(new WorldPoint(3040, 9740, 0),
|
||||
new Rock(4, Ore.IRON), new Rock(37, Ore.COAL), new Rock(5, Ore.MITHRIL), new Rock(2, Ore.ADAMANTITE)),
|
||||
MINING_GUILD_SOUTH(new WorldPoint(3032, 9720, 0),
|
||||
new Rock(8, Ore.IRON), new Rock(20, Ore.COAL), new Rock(10, Ore.MITHRIL), new Rock(8, Ore.ADAMANTITE),
|
||||
new Rock(2, Ore.RUNITE)),
|
||||
MISCELLANIA(new WorldPoint(2526, 3891, 0), new Rock(9, Ore.COAL)),
|
||||
MISCELLANIA_DUNGEON(new WorldPoint(2504, 10287, 0), new Rock(4, Ore.COAL)),
|
||||
MOR_UL_REK_NORTH(new WorldPoint(2458, 5167, 0), new Rock(3, Ore.SILVER), new Rock(3, Ore.GOLD)),
|
||||
MOR_UL_REK_SOUTH_EAST(new WorldPoint(2513, 5074, 0), new Rock(6, Ore.SILVER), new Rock(7, Ore.GOLD)),
|
||||
MOR_UL_REK_SOUTH_WEST(new WorldPoint(2499, 5062, 0),
|
||||
new Rock(3, Ore.IRON), new Rock(4, Ore.COAL), new Rock(2, Ore.ADAMANTITE), new Rock(3, Ore.RUNITE)),
|
||||
MOUNT_KARUULM(new WorldPoint(1278, 3814, 0), new Rock(6, Ore.IRON), new Rock(5, Ore.COAL)),
|
||||
// MOURNER_TUNNELS -- NOT AVAILABLE ON WORLD MAP
|
||||
MYTHS_GUILD(new WorldPoint(1936, 9020, 0), new Rock(4, Ore.ADAMANTITE), new Rock(2, Ore.RUNITE)),
|
||||
OGRESS_SETTLEMENT(new WorldPoint(1977, 9041, 0),
|
||||
new Rock(5, Ore.COAL), new Rock(2, Ore.MITHRIL), new Rock(1, Ore.ADAMANTITE)),
|
||||
PIRATES_HIDEOUT(new WorldPoint(3056, 3945, 0),
|
||||
new Rock(1, Ore.IRON), new Rock(4, Ore.COAL), new Rock(4, Ore.MITHRIL), new Rock(1, Ore.ADAMANTITE)),
|
||||
PISCARILLIUS(new WorldPoint(1759, 3718, 0),
|
||||
new Rock(5, Ore.COPPER), new Rock(6, Ore.TIN), new Rock(5, Ore.IRON), new Rock(2, Ore.SILVER),
|
||||
new Rock(1, Ore.MITHRIL)),
|
||||
PISCATORIS(new WorldPoint(2337, 3640, 0),
|
||||
new Rock(2, Ore.CLAY), new Rock(2, Ore.COPPER), new Rock(2, Ore.TIN), new Rock(3, Ore.IRON)),
|
||||
PORT_KHAZARD(new WorldPoint(2651, 3172, 0),
|
||||
new Rock(2, Ore.COPPER), new Rock(2, Ore.TIN), new Rock(2, Ore.MITHRIL)),
|
||||
RELLEKKA(new WorldPoint(2682, 3704, 0), new Rock(4, Ore.CLAY), new Rock(3, Ore.SILVER), new Rock(7, Ore.COAL)),
|
||||
RIMMINGTON(new WorldPoint(2977, 3240, 0),
|
||||
new Rock(2, Ore.CLAY), new Rock(5, Ore.COPPER), new Rock(2, Ore.TIN), new Rock(6, Ore.IRON),
|
||||
new Rock(2, Ore.GOLD)),
|
||||
SALT_MINE(new WorldPoint(2835, 10334, 0),
|
||||
new Rock(7, Ore.BASALT), new Rock(15, Ore.TE_SALT), new Rock(12, Ore.EFH_SALT), new Rock(12, Ore.URT_SALT)),
|
||||
SHAYZIEN_EAST(new WorldPoint(1597, 3653, 0), new Rock(3, Ore.CLAY), new Rock(1, Ore.MITHRIL), new Rock(1, Ore.ADAMANTITE)),
|
||||
SHAYZIEN_WEST(new WorldPoint(1586, 3650, 0),
|
||||
new Rock(4, Ore.IRON), new Rock(4, Ore.COAL), new Rock(1, Ore.MITHRIL), new Rock(1, Ore.ADAMANTITE)),
|
||||
SHILO_VILLAGE_SURFACE(new WorldPoint(2822, 3001, 0), new Rock(7, Ore.GEM_ROCK)),
|
||||
SILVAREA(new WorldPoint(3371, 3498, 0), new Rock(7, Ore.LIMESTONE)),
|
||||
SLEPE_UNDERGROUND(new WorldPoint(3888, 9749, 0), new Rock(6, Ore.IRON), new Rock(14, Ore.COAL)),
|
||||
TRAHEARN(new WorldPoint(3295, 12387, 0),
|
||||
new Rock(26, Ore.IRON), new Rock(8, Ore.SILVER), new Rock(19, Ore.COAL), new Rock(14, Ore.GOLD),
|
||||
new Rock(7, Ore.MITHRIL), new Rock(10, Ore.SOFT_CLAY), new Rock(7, Ore.ADAMANTITE), new Rock(4, Ore.RUNITE)),
|
||||
// TUTORIAL ISLAND -- NOT AVAILABLE ON WORLD MAP
|
||||
UZER(new WorldPoint(3415, 3160, 0), new Rock(10, Ore.CLAY)),
|
||||
VARROCK_SOUTH_EAST(new WorldPoint(3286, 3365, 0),
|
||||
new Rock(9, Ore.COPPER), new Rock(6, Ore.TIN), new Rock(4, Ore.IRON)),
|
||||
VARROCK_SOUTH_WEST(new WorldPoint(3176, 3370, 0),
|
||||
new Rock(3, Ore.CLAY), new Rock(8, Ore.TIN), new Rock(3, Ore.IRON), new Rock(3, Ore.SILVER)),
|
||||
VERDANT_VALLEY(new WorldPoint(3766, 3757, 0), true, new Rock(3, Ore.IRON)),
|
||||
WILDERNESS_RESOURCE_AREA(new WorldPoint(3192, 3930, 0),
|
||||
new Rock(6, Ore.IRON), new Rock(11, Ore.COAL), new Rock(4, Ore.GOLD), new Rock(1, Ore.MITHRIL), new Rock(6, Ore.ADAMANTITE)),
|
||||
WILDERNESS_SOUTH(new WorldPoint(3104, 3569, 0), new Rock(2, Ore.IRON), new Rock(3, Ore.COAL)),
|
||||
WILDERNESS_SOUTH_WEST(new WorldPoint(3013, 3589, 0), new Rock(34, Ore.COAL)),
|
||||
;
|
||||
|
||||
private final WorldPoint location;
|
||||
private final String tooltip;
|
||||
private final boolean iconRequired;
|
||||
|
||||
MiningSiteLocation(WorldPoint location, Rock... rocks)
|
||||
{
|
||||
this(location, false, rocks);
|
||||
}
|
||||
|
||||
MiningSiteLocation(WorldPoint location, boolean iconRequired, Rock... rocks)
|
||||
{
|
||||
this.location = location;
|
||||
this.iconRequired = iconRequired;
|
||||
this.tooltip = createTooltip(rocks);
|
||||
}
|
||||
|
||||
private String createTooltip(Rock[] rocks)
|
||||
{
|
||||
return Joiner.on("<br>").join(rocks);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private enum Ore
|
||||
{
|
||||
ROCK("Rock"),
|
||||
CLAY("Clay"),
|
||||
COPPER("Copper"),
|
||||
TIN("Tin"),
|
||||
LIMESTONE("Limestone"),
|
||||
BLURITE("Blurite"),
|
||||
IRON("Iron"),
|
||||
ELEMENTAL("Elemental"),
|
||||
SILVER("Silver"),
|
||||
COAL("Coal"),
|
||||
SANDSTONE("Sandstone"),
|
||||
DENSE_ESSENCE("Dense essence"),
|
||||
DAEYALT_ESSENCE("Daeyalt essence"),
|
||||
GOLD("Gold"),
|
||||
GEM_ROCK("Gem rock"),
|
||||
HARD_ROCK("Hard rock"),
|
||||
VOLCANIC_SULPHUR("Volcanic sulphur"),
|
||||
GRANITE("Granite"),
|
||||
MITHRIL("Mithril"),
|
||||
LUNAR("Lunar"),
|
||||
LOVAKITE("Lovakite"),
|
||||
ADAMANTITE("Adamantite"),
|
||||
SOFT_CLAY("Soft clay"),
|
||||
BASALT("Basalt"),
|
||||
TE_SALT("Te salt"),
|
||||
EFH_SALT("Efh salt"),
|
||||
URT_SALT("Urt salt"),
|
||||
RUNITE("Runite"),
|
||||
AMETHYST("Amethyst"),
|
||||
;
|
||||
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class Rock
|
||||
{
|
||||
private final int count;
|
||||
private final Ore ore;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return count + " " + ore;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020, dekvall <https://github.com/dekvall>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
class MiningSitePoint extends WorldMapPoint
|
||||
{
|
||||
MiningSitePoint(MiningSiteLocation point, BufferedImage icon)
|
||||
{
|
||||
super(point.getLocation(), icon);
|
||||
setTooltip(point.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2018, John James Hamilton <https://github.com/johnhamilto>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.Quest;
|
||||
|
||||
// Some quests are in the same spot, but they are done in order. If multiple
|
||||
// quests start in the same location, an array of quests is expected.
|
||||
enum QuestStartLocation
|
||||
{
|
||||
//Free Quests
|
||||
COOKS_ASSISTANT_RFD(Quest.COOKS_ASSISTANT, new WorldPoint(3211, 3216, 0)),
|
||||
THE_CORSAIR_CURSE(Quest.THE_CORSAIR_CURSE, new WorldPoint(3029, 3273, 0)),
|
||||
DEMON_SLAYER(Quest.DEMON_SLAYER, new WorldPoint(3204, 3424, 0)),
|
||||
DORICS_QUEST(Quest.DORICS_QUEST, new WorldPoint(2952, 3450, 0)),
|
||||
DRAGON_SLAYER(Quest.DRAGON_SLAYER, new WorldPoint(3190, 3362, 0)),
|
||||
ERNEST_THE_CHICKEN(Quest.ERNEST_THE_CHICKEN, new WorldPoint(3109, 3330, 0)),
|
||||
GOBLIN_DIPLOMACY(Quest.GOBLIN_DIPLOMACY, new WorldPoint(2957, 3509, 0)),
|
||||
IMP_CATCHER(Quest.IMP_CATCHER, new WorldPoint(3108, 3160, 0)),
|
||||
THE_KNIGHTS_SWORD(Quest.THE_KNIGHTS_SWORD, new WorldPoint(2976, 3342, 0)),
|
||||
MISTHALIN_MYSTERY(Quest.MISTHALIN_MYSTERY, new WorldPoint(3235, 3155, 0)),
|
||||
PIRATES_TREASURE(Quest.PIRATES_TREASURE, new WorldPoint(3051, 3252, 0)),
|
||||
PRINCE_ALI_RESCUE(Quest.PRINCE_ALI_RESCUE, new WorldPoint(3301, 3163, 0)),
|
||||
THE_RESTLESS_GHOST(Quest.THE_RESTLESS_GHOST, new WorldPoint(3240, 3210, 0)),
|
||||
RUNE_MYSTERIES(Quest.RUNE_MYSTERIES, new WorldPoint(3210, 3220, 0)),
|
||||
SHEEP_SHEARER(Quest.SHEEP_SHEARER, new WorldPoint(3190, 3272, 0)),
|
||||
SHIELD_OF_ARRAV_PHOENIX_GANG(Quest.SHIELD_OF_ARRAV, new WorldPoint(3208, 3495, 0)),
|
||||
SHIELD_OF_ARRAV_BLACK_ARM_GANG(Quest.SHIELD_OF_ARRAV, new WorldPoint(3208, 3392, 0)),
|
||||
VAMPYRE_SLAYER(Quest.VAMPYRE_SLAYER, new WorldPoint(3096, 3266, 0)),
|
||||
WITCHS_POTION(Quest.WITCHS_POTION, new WorldPoint(2967, 3203, 0)),
|
||||
X_MARKS_THE_SPOT(Quest.X_MARKS_THE_SPOT, new WorldPoint(3227, 3242, 0)),
|
||||
|
||||
//Members' Quests
|
||||
ANIMAL_MAGNETISM(Quest.ANIMAL_MAGNETISM, new WorldPoint(3094, 3360, 0)),
|
||||
ANOTHER_SLICE_OF_HAM(Quest.ANOTHER_SLICE_OF_HAM, new WorldPoint(2799, 5428, 0)),
|
||||
THE_ASCENT_OF_ARCEUUS(Quest.THE_ASCENT_OF_ARCEUUS, new WorldPoint(1699, 3742, 0)),
|
||||
BETWEEN_A_ROCK(Quest.BETWEEN_A_ROCK, new WorldPoint(2823, 10168, 0)),
|
||||
BIG_CHOMPY_BIRD_HUNTING(Quest.BIG_CHOMPY_BIRD_HUNTING, new WorldPoint(2629, 2981, 0)),
|
||||
BIOHAZARD(Quest.BIOHAZARD, new WorldPoint(2591, 3335, 0)),
|
||||
BONE_VOYAGE(Quest.BONE_VOYAGE, new WorldPoint(3259, 3450, 0)),
|
||||
CABIN_FEVER(Quest.CABIN_FEVER, new WorldPoint(3674, 3496, 0)),
|
||||
CLIENT_OF_KOUREND(Quest.CLIENT_OF_KOUREND, new WorldPoint(1823, 3690, 0)),
|
||||
CLOCK_TOWER(Quest.CLOCK_TOWER, new WorldPoint(2568, 3249, 0)),
|
||||
COLD_WAR(Quest.COLD_WAR, new WorldPoint(2593, 3265, 0)),
|
||||
CONTACT(Quest.CONTACT, new WorldPoint(3280, 2770, 0)),
|
||||
CREATURE_OF_FENKENSTRAIN(Quest.CREATURE_OF_FENKENSTRAIN, new WorldPoint(3487, 3485, 0)),
|
||||
DARKNESS_OF_HALLOWVALE(Quest.DARKNESS_OF_HALLOWVALE, new WorldPoint(3494, 9628, 0)),
|
||||
DEATH_PLATEAU_TROLL_STRONGHOLD(new Quest[]{Quest.DEATH_PLATEAU, Quest.TROLL_STRONGHOLD}, new WorldPoint(2895, 3528, 0)),
|
||||
DEATH_TO_THE_DORGESHUUN(Quest.DEATH_TO_THE_DORGESHUUN, new WorldPoint(3316, 9613, 0)),
|
||||
THE_DEPTHS_OF_DESPAIR(Quest.THE_DEPTHS_OF_DESPAIR, new WorldPoint(1781, 3570, 0)),
|
||||
DESERT_TREASURE(Quest.DESERT_TREASURE, new WorldPoint(3177, 3043, 0)),
|
||||
DEVIOUS_MINDS(Quest.DEVIOUS_MINDS, new WorldPoint(3405, 3492, 0)),
|
||||
THE_DIG_SITE(Quest.THE_DIG_SITE, new WorldPoint(3363, 3337, 0)),
|
||||
DRAGON_SLAYER_II(Quest.DRAGON_SLAYER_II, new WorldPoint(2456, 2868, 0)),
|
||||
DREAM_MENTOR(Quest.DREAM_MENTOR, new WorldPoint(2144, 10346, 0)),
|
||||
DRUIDIC_RITUAL(Quest.DRUIDIC_RITUAL, new WorldPoint(2916, 3484, 0)),
|
||||
DWARF_CANNON(Quest.DWARF_CANNON, new WorldPoint(2566, 3461, 0)),
|
||||
EADGARS_RUSE(Quest.EADGARS_RUSE, new WorldPoint(2896, 3426, 0)),
|
||||
EAGLES_PEAK(Quest.EAGLES_PEAK, new WorldPoint(2605, 3264, 0)),
|
||||
ELEMENTAL_WORKSHOP(new Quest[]{Quest.ELEMENTAL_WORKSHOP_I, Quest.ELEMENTAL_WORKSHOP_II}, new WorldPoint(2714, 3482, 0)),
|
||||
ENAKHRAS_LAMENT(Quest.ENAKHRAS_LAMENT, new WorldPoint(3190, 2926, 0)),
|
||||
ENLIGHTENED_JOURNEY(Quest.ENLIGHTENED_JOURNEY, new WorldPoint(2809, 3356, 0)),
|
||||
THE_EYES_OF_GLOUPHRIE(Quest.THE_EYES_OF_GLOUPHRIE, new WorldPoint(2400, 3419, 0)),
|
||||
FAIRYTALE(new Quest[]{Quest.FAIRYTALE_I__GROWING_PAINS, Quest.FAIRYTALE_II__CURE_A_QUEEN}, new WorldPoint(3077, 3258, 0)),
|
||||
FAMILY_CREST(Quest.FAMILY_CREST, new WorldPoint(3278, 3404, 0)),
|
||||
THE_FEUD(Quest.THE_FEUD, new WorldPoint(3301, 3211, 0)),
|
||||
FIGHT_ARENA(Quest.FIGHT_ARENA, new WorldPoint(2565, 3199, 0)),
|
||||
FISHING_CONTEST_1(Quest.FISHING_CONTEST, new WorldPoint(2875, 3483, 0)),
|
||||
FISHING_CONTEST_2(Quest.FISHING_CONTEST, new WorldPoint(2820, 3487, 0)),
|
||||
FORGETTABLE_TALE(Quest.FORGETTABLE_TALE, new WorldPoint(2826, 10215, 0)),
|
||||
THE_FORSAKEN_TOWER(Quest.THE_FORSAKEN_TOWER, new WorldPoint(1482, 3748, 0)),
|
||||
THE_FREMENNIK_ISLES(Quest.THE_FREMENNIK_ISLES, new WorldPoint(2645, 3711, 0)),
|
||||
THE_FREMENNIK_TRIALS(Quest.THE_FREMENNIK_TRIALS, new WorldPoint(2657, 3669, 0)),
|
||||
THE_FREMENNIK_EXILES(Quest.THE_FREMENNIK_EXILES, new WorldPoint(2658, 3669, 0)),
|
||||
GARDEN_OF_TRANQUILLITY(Quest.GARDEN_OF_TRANQUILLITY, new WorldPoint(3227, 3477, 0)),
|
||||
GERTRUDES_CAT_RATCATCHERS(Quest.GERTRUDES_CAT, new WorldPoint(3150, 3411, 0)),
|
||||
GETTING_AHEAD(Quest.GETTING_AHEAD, new WorldPoint(1247, 3686, 0)),
|
||||
GHOSTS_AHOY(Quest.GHOSTS_AHOY, new WorldPoint(3677, 3510, 0)),
|
||||
THE_GIANT_DWARF(Quest.THE_GIANT_DWARF, new WorldPoint(2841, 10129, 0)),
|
||||
THE_GOLEM(Quest.THE_GOLEM, new WorldPoint(3487, 3089, 0)),
|
||||
THE_GRAND_TREE_MONKEY_MADNESS(new Quest[]{Quest.THE_GRAND_TREE, Quest.MONKEY_MADNESS_I, Quest.MONKEY_MADNESS_II}, new WorldPoint(2466, 3497, 0)),
|
||||
THE_GREAT_BRAIN_ROBBERY(Quest.THE_GREAT_BRAIN_ROBBERY, new WorldPoint(3681, 2963, 0)),
|
||||
GRIM_TALES(Quest.GRIM_TALES, new WorldPoint(2890, 3454, 0)),
|
||||
THE_HAND_IN_THE_SAND(Quest.THE_HAND_IN_THE_SAND, new WorldPoint(2552, 3101, 0)),
|
||||
HAUNTED_MINE(Quest.HAUNTED_MINE, new WorldPoint(3443, 3258, 0)),
|
||||
HAZEEL_CULT(Quest.HAZEEL_CULT, new WorldPoint(2565, 3271, 0)),
|
||||
HEROES_QUEST(Quest.HEROES_QUEST, new WorldPoint(2903, 3511, 0)),
|
||||
HOLY_GRAIL(new Quest[]{Quest.MERLINS_CRYSTAL, Quest.HOLY_GRAIL}, new WorldPoint(2763, 3515, 0)),
|
||||
HORROR_FROM_THE_DEEP(Quest.HORROR_FROM_THE_DEEP, new WorldPoint(2507, 3635, 0)),
|
||||
ICTHLARINS_LITTLE_HELPER(Quest.ICTHLARINS_LITTLE_HELPER, new WorldPoint(3314, 2849, 0)),
|
||||
IN_SEARCH_OF_THE_MYREQUE(Quest.IN_SEARCH_OF_THE_MYREQUE, new WorldPoint(3502, 3477, 0)),
|
||||
JUNGLE_POTION(Quest.JUNGLE_POTION, new WorldPoint(2809, 3086, 0)),
|
||||
KINGS_RANSOM(Quest.KINGS_RANSOM, new WorldPoint(2741, 3554, 0)),
|
||||
LEGENDS_QUEST(Quest.LEGENDS_QUEST, new WorldPoint(2725, 3367, 0)),
|
||||
LOST_CITY(Quest.LOST_CITY, new WorldPoint(3149, 3205, 0)),
|
||||
THE_LOST_TRIBE(Quest.THE_LOST_TRIBE, new WorldPoint(3211, 3224, 0)),
|
||||
LUNAR_DIPLOMACY(Quest.LUNAR_DIPLOMACY, new WorldPoint(2618, 3691, 0)),
|
||||
MAKING_FRIENDS_WITH_MY_ARM(Quest.MAKING_FRIENDS_WITH_MY_ARM, new WorldPoint(2904, 10092, 0)),
|
||||
MAKING_HISTORY(Quest.MAKING_HISTORY, new WorldPoint(2435, 3346, 0)),
|
||||
MONKS_FRIEND(Quest.MONKS_FRIEND, new WorldPoint(2605, 3209, 0)),
|
||||
MOUNTAIN_DAUGHTER(Quest.MOUNTAIN_DAUGHTER, new WorldPoint(2810, 3672, 0)),
|
||||
MOURNINGS_ENDS_PART_I(Quest.MOURNINGS_END_PART_I, new WorldPoint(2289, 3149, 0)),
|
||||
MOURNINGS_ENDS_PART_II(Quest.MOURNINGS_END_PART_II, new WorldPoint(2352, 3172, 0)),
|
||||
MURDER_MYSTERY(Quest.MURDER_MYSTERY, new WorldPoint(2740, 3562, 0)),
|
||||
MY_ARMS_BIG_ADVENTURE(Quest.MY_ARMS_BIG_ADVENTURE, new WorldPoint(2908, 10088, 0)),
|
||||
NATURE_SPIRIT(Quest.NATURE_SPIRIT, new WorldPoint(3440, 9894, 0)),
|
||||
OBSERVATORY_QUEST(Quest.OBSERVATORY_QUEST, new WorldPoint(2438, 3185, 0)),
|
||||
OLAFS_QUEST(Quest.OLAFS_QUEST, new WorldPoint(2723, 3729, 0)),
|
||||
ONE_SMALL_FAVOUR(Quest.ONE_SMALL_FAVOUR, new WorldPoint(2834, 2985, 0)),
|
||||
PLAGUE_CITY_SONG_OF_THE_ELVES(new Quest[]{Quest.PLAGUE_CITY, Quest.SONG_OF_THE_ELVES}, new WorldPoint(2567, 3334, 0)),
|
||||
A_PORCINE_OF_INTEREST(Quest.A_PORCINE_OF_INTEREST, new WorldPoint(3085, 3251, 0)),
|
||||
PRIEST_IN_PERIL(Quest.PRIEST_IN_PERIL, new WorldPoint(3219, 3473, 0)),
|
||||
THE_QUEEN_OF_THIEVES(Quest.THE_QUEEN_OF_THIEVES, new WorldPoint(1795, 3782, 0)),
|
||||
RAG_AND_BONE_MAN(new Quest[]{Quest.RAG_AND_BONE_MAN, Quest.RAG_AND_BONE_MAN_II}, new WorldPoint(3359, 3504, 0)),
|
||||
RECRUITMENT_DRIVE_BLACK_KNIGHTS_FORTRESS(new Quest[]{Quest.BLACK_KNIGHTS_FORTRESS, Quest.RECRUITMENT_DRIVE}, new WorldPoint(2959, 3336, 0)),
|
||||
ROVING_ELVES(Quest.ROVING_ELVES, new WorldPoint(2288, 3146, 0)),
|
||||
RUM_DEAL(Quest.RUM_DEAL, new WorldPoint(3679, 3535, 0)),
|
||||
SCORPION_CATCHER(Quest.SCORPION_CATCHER, new WorldPoint(2701, 3399, 0)),
|
||||
SEA_SLUG(Quest.SEA_SLUG, new WorldPoint(2715, 3302, 0)),
|
||||
SHADES_OF_MORTTON(Quest.SHADES_OF_MORTTON, new WorldPoint(3463, 3308, 0)),
|
||||
SHADOW_OF_THE_STORM(Quest.SHADOW_OF_THE_STORM, new WorldPoint(3270, 3159, 0)),
|
||||
SHEEP_HERDER(Quest.SHEEP_HERDER, new WorldPoint(2616, 3299, 0)),
|
||||
SHILO_VILLAGE(Quest.SHILO_VILLAGE, new WorldPoint(2882, 2951, 0)),
|
||||
SINS_OF_THE_FATHER(Quest.SINS_OF_THE_FATHER, new WorldPoint(3728, 3319, 0)),
|
||||
A_SOULS_BANE(Quest.A_SOULS_BANE, new WorldPoint(3307, 3454, 0)),
|
||||
SPIRITS_OF_THE_ELID(Quest.SPIRITS_OF_THE_ELID, new WorldPoint(3441, 2911, 0)),
|
||||
SWAN_SONG(Quest.SWAN_SONG, new WorldPoint(2345, 3652, 0)),
|
||||
TAI_BWO_WANNAI_TRIO(Quest.TAI_BWO_WANNAI_TRIO, new WorldPoint(2779, 3087, 0)),
|
||||
A_TAIL_OF_TWO_CATS(Quest.A_TAIL_OF_TWO_CATS, new WorldPoint(2917, 3557, 0)),
|
||||
TALE_OF_THE_RIGHTEOUS(Quest.TALE_OF_THE_RIGHTEOUS, new WorldPoint(1511, 3631, 0)),
|
||||
A_TASTE_OF_HOPE(Quest.A_TASTE_OF_HOPE, new WorldPoint(3668, 3216, 0)),
|
||||
TEARS_OF_GUTHIX(Quest.TEARS_OF_GUTHIX, new WorldPoint(3251, 9517, 0)),
|
||||
TEMPLE_OF_IKOV(Quest.TEMPLE_OF_IKOV, new WorldPoint(2574, 3320, 0)),
|
||||
THRONE_OF_MISCELLANIA_ROYAL_TROUBLE(new Quest[]{Quest.THRONE_OF_MISCELLANIA, Quest.ROYAL_TROUBLE}, new WorldPoint(2497, 3859, 0)),
|
||||
THE_TOURIST_TRAP(Quest.THE_TOURIST_TRAP, new WorldPoint(3302, 3113, 0)),
|
||||
TOWER_OF_LIFE(Quest.TOWER_OF_LIFE, new WorldPoint(2640, 3218, 0)),
|
||||
TREE_GNOME_VILLAGE(Quest.TREE_GNOME_VILLAGE, new WorldPoint(2541, 3169, 0)),
|
||||
TRIBAL_TOTEM(Quest.TRIBAL_TOTEM, new WorldPoint(2790, 3182, 0)),
|
||||
TROLL_ROMANCE(Quest.TROLL_ROMANCE, new WorldPoint(2890, 10097, 0)),
|
||||
UNDERGROUND_PASS_REGICIDE(new Quest[]{Quest.REGICIDE, Quest.UNDERGROUND_PASS}, new WorldPoint(2575, 3293, 0)),
|
||||
WANTED_SLUG_MENACE(new Quest[]{Quest.WANTED, Quest.THE_SLUG_MENACE}, new WorldPoint(2996, 3373, 0)),
|
||||
WATCHTOWER(Quest.WATCHTOWER, new WorldPoint(2545, 3112, 0)),
|
||||
WATERFALL_QUEST(Quest.WATERFALL_QUEST, new WorldPoint(2521, 3498, 0)),
|
||||
WHAT_LIES_BELOW(Quest.WHAT_LIES_BELOW, new WorldPoint(3265, 3333, 0)),
|
||||
WITCHS_HOUSE(Quest.WITCHS_HOUSE, new WorldPoint(2927, 3456, 0)),
|
||||
ZOGRE_FLESH_EATERS(Quest.ZOGRE_FLESH_EATERS, new WorldPoint(2442, 3051, 0));
|
||||
|
||||
@Getter
|
||||
private final WorldPoint location;
|
||||
|
||||
@Getter
|
||||
private final Quest[] quests;
|
||||
|
||||
QuestStartLocation(Quest[] quests, WorldPoint location)
|
||||
{
|
||||
this.location = location;
|
||||
this.quests = quests;
|
||||
}
|
||||
|
||||
QuestStartLocation(Quest quest, WorldPoint location)
|
||||
{
|
||||
this.location = location;
|
||||
this.quests = new Quest[]{quest};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018, John James Hamilton <https://github.com/johnhamilto>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
class QuestStartPoint extends WorldMapPoint
|
||||
{
|
||||
QuestStartPoint(WorldPoint location, BufferedImage icon, String tooltip)
|
||||
{
|
||||
super(location, icon);
|
||||
setTooltip(tooltip);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Spedwards <https://github.com/Spedwards>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum RareTreeLocation
|
||||
{
|
||||
WILLOW("Willow tree", 30,
|
||||
// Kandarin
|
||||
new WorldPoint(2710, 3510, 0)),
|
||||
|
||||
TEAK("Teak tree", 35,
|
||||
// Ape Atoll
|
||||
new WorldPoint(2774, 2697, 0),
|
||||
|
||||
// Desert
|
||||
new WorldPoint(3510, 3073, 0),
|
||||
|
||||
// Mos Le'Harmless
|
||||
new WorldPoint(3832, 3067, 0),
|
||||
|
||||
// Karamja
|
||||
new WorldPoint(2837, 2907, 0),
|
||||
new WorldPoint(2899, 2897, 0),
|
||||
|
||||
// Feldip Hills
|
||||
new WorldPoint(2333, 3049, 0),
|
||||
|
||||
// Prifddinas
|
||||
new WorldPoint(3309, 6123, 0)),
|
||||
|
||||
SWAYING("Swaying tree", 40,
|
||||
// The Fremennik Trials
|
||||
new WorldPoint(2738, 3639, 0)),
|
||||
|
||||
MATURE_JUNIPER("Mature juniper tree", 42,
|
||||
// Zeah
|
||||
new WorldPoint(1690, 3524, 0)),
|
||||
|
||||
MAPLE("Maple tree", 45,
|
||||
// Zeah
|
||||
new WorldPoint(1231, 3704, 0),
|
||||
new WorldPoint(1293, 3756, 0),
|
||||
new WorldPoint(1640, 3496, 0),
|
||||
new WorldPoint(1613, 3494, 0),
|
||||
new WorldPoint(1560, 3636, 0),
|
||||
new WorldPoint(1646, 3590, 0),
|
||||
|
||||
// Miscellania
|
||||
new WorldPoint(2550, 3869, 0),
|
||||
|
||||
// Kandarin
|
||||
new WorldPoint(2712, 3382, 0),
|
||||
new WorldPoint(2720, 3465, 0),
|
||||
new WorldPoint(2726, 3501, 0),
|
||||
new WorldPoint(2728, 3481, 0),
|
||||
new WorldPoint(2748, 3466, 0),
|
||||
new WorldPoint(2710, 3570, 0),
|
||||
|
||||
// Prifddinas
|
||||
new WorldPoint(2209, 3427, 0),
|
||||
new WorldPoint(3233, 6179, 0)),
|
||||
|
||||
MAHOGANY("Mahogany tree", 50,
|
||||
// Zeah
|
||||
new WorldPoint(1237, 3770, 0),
|
||||
|
||||
// Ape Atoll
|
||||
new WorldPoint(2716, 2710, 0),
|
||||
new WorldPoint(2725, 2735, 0),
|
||||
|
||||
// Mos Le'Harmless
|
||||
new WorldPoint(3824, 3053, 0),
|
||||
|
||||
// Karamja
|
||||
new WorldPoint(2946, 2908, 0),
|
||||
|
||||
// Prifddinas
|
||||
new WorldPoint(3301, 6129, 0)),
|
||||
|
||||
TEAK_MAHOGANY("Teak/Mahogany trees", 50,
|
||||
// Miscellania
|
||||
new WorldPoint(2602, 3895, 0),
|
||||
|
||||
// Mos Le'Harmless
|
||||
new WorldPoint(3810, 3058, 0),
|
||||
|
||||
// Karamja
|
||||
new WorldPoint(2821, 3084, 0)),
|
||||
|
||||
YEW("Yew tree", 60,
|
||||
// Zeah
|
||||
new WorldPoint(1217, 3688, 0),
|
||||
new WorldPoint(1353, 3731, 0),
|
||||
new WorldPoint(1529, 3452, 0),
|
||||
new WorldPoint(1591, 3421, 0),
|
||||
new WorldPoint(1647, 3508, 0),
|
||||
new WorldPoint(1621, 3512, 0),
|
||||
new WorldPoint(1593, 3491, 0),
|
||||
new WorldPoint(1583, 3499, 0),
|
||||
new WorldPoint(1696, 3554, 0),
|
||||
new WorldPoint(1625, 3677, 0),
|
||||
new WorldPoint(1625, 3669, 0),
|
||||
new WorldPoint(1642, 3683, 0),
|
||||
new WorldPoint(1642, 3663, 0),
|
||||
new WorldPoint(1642, 3533, 0),
|
||||
new WorldPoint(1671, 3657, 0),
|
||||
new WorldPoint(1680, 3657, 0),
|
||||
|
||||
// Tirannwn
|
||||
new WorldPoint(2217, 3141, 0),
|
||||
|
||||
// Prifddinas
|
||||
new WorldPoint(3288, 6066, 0),
|
||||
new WorldPoint(3305, 6032, 0),
|
||||
|
||||
// Kandarin
|
||||
new WorldPoint(2315, 3610, 0),
|
||||
new WorldPoint(2331, 3514, 0),
|
||||
new WorldPoint(2358, 3510, 0),
|
||||
new WorldPoint(2360, 3471, 0),
|
||||
new WorldPoint(2434, 3432, 0),
|
||||
new WorldPoint(2493, 3396, 0),
|
||||
new WorldPoint(2495, 3490, 0),
|
||||
new WorldPoint(2733, 3334, 0),
|
||||
new WorldPoint(2757, 3431, 0),
|
||||
new WorldPoint(2714, 3460, 0),
|
||||
|
||||
// Asgarnia
|
||||
new WorldPoint(2995, 3312, 0),
|
||||
new WorldPoint(3018, 3316, 0),
|
||||
new WorldPoint(3041, 3320, 0),
|
||||
new WorldPoint(3052, 3272, 0),
|
||||
new WorldPoint(2931, 3231, 0),
|
||||
|
||||
// Misthalin
|
||||
new WorldPoint(3085, 3481, 0),
|
||||
new WorldPoint(3085, 3469, 0),
|
||||
new WorldPoint(3146, 3255, 0),
|
||||
new WorldPoint(3151, 3231, 0),
|
||||
new WorldPoint(3165, 3220, 0),
|
||||
new WorldPoint(3184, 3227, 0),
|
||||
new WorldPoint(3251, 3364, 0),
|
||||
new WorldPoint(3204, 3504, 0),
|
||||
new WorldPoint(3208, 3500, 0),
|
||||
new WorldPoint(3221, 3503, 0),
|
||||
new WorldPoint(3248, 3473, 0),
|
||||
new WorldPoint(3266, 3494, 0),
|
||||
new WorldPoint(3270, 3471, 0),
|
||||
new WorldPoint(3304, 3470, 0),
|
||||
new WorldPoint(3249, 3202, 0),
|
||||
|
||||
// Morytania
|
||||
new WorldPoint(3674, 3447, 0),
|
||||
new WorldPoint(3684, 3385, 0),
|
||||
|
||||
// Zanaris
|
||||
new WorldPoint(2412, 4464, 0),
|
||||
new WorldPoint(2465, 4427, 0),
|
||||
new WorldPoint(2491, 4426, 0)),
|
||||
|
||||
MAPLE_YEW("Maple/Yew trees", 60,
|
||||
// Feldip Hills
|
||||
new WorldPoint(2476, 2893, 0)),
|
||||
|
||||
SULLIUSCEP("Sulliuscep", 65,
|
||||
// Fossil Island
|
||||
new WorldPoint(3662, 3802, 0),
|
||||
new WorldPoint(3662, 3781, 0),
|
||||
new WorldPoint(3677, 3806, 0),
|
||||
new WorldPoint(3677, 3733, 0),
|
||||
new WorldPoint(3682, 3775, 0),
|
||||
new WorldPoint(3682, 3758, 0)),
|
||||
|
||||
MAGIC("Magic tree", 75,
|
||||
// Zeah
|
||||
new WorldPoint(1373, 3821, 0),
|
||||
new WorldPoint(1389, 3821, 0),
|
||||
new WorldPoint(1610, 3443, 0),
|
||||
new WorldPoint(1578, 3488, 0),
|
||||
new WorldPoint(1685, 3740, 0),
|
||||
new WorldPoint(1681, 3689, 0),
|
||||
new WorldPoint(1751, 3564, 0),
|
||||
new WorldPoint(1796, 3600, 0),
|
||||
|
||||
// Misthalin
|
||||
new WorldPoint(3355, 3312, 0),
|
||||
new WorldPoint(3368, 3312, 0),
|
||||
|
||||
// Tirannwn
|
||||
new WorldPoint(2284, 3141, 0),
|
||||
|
||||
// Prifddinas
|
||||
new WorldPoint(3229, 6101, 0),
|
||||
|
||||
// Kandarin
|
||||
new WorldPoint(2371, 3427, 0),
|
||||
new WorldPoint(2432, 3411, 0),
|
||||
new WorldPoint(2490, 3414, 0),
|
||||
new WorldPoint(2704, 3397, 0),
|
||||
new WorldPoint(2695, 3423, 0),
|
||||
|
||||
// Feldip Hills
|
||||
new WorldPoint(2443, 2845, 0),
|
||||
|
||||
// Wilderness
|
||||
new WorldPoint(3175, 3931, 0)),
|
||||
|
||||
REDWOOD("Redwood tree", 90,
|
||||
// Zeah
|
||||
new WorldPoint(1569, 3493, 0),
|
||||
new WorldPoint(1569, 3483, 0));
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint[] locations;
|
||||
private final int levelReq;
|
||||
|
||||
RareTreeLocation(String description, int level, WorldPoint... locations)
|
||||
{
|
||||
this.tooltip = description + " - Level " + level;
|
||||
this.locations = locations;
|
||||
this.levelReq = level;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Spedwards <https://github.com/Spedwards>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
class RareTreePoint extends WorldMapPoint
|
||||
{
|
||||
RareTreePoint(WorldPoint point, String tooltip, BufferedImage icon, boolean showTooltip)
|
||||
{
|
||||
super(point, icon);
|
||||
|
||||
if (showTooltip)
|
||||
{
|
||||
setTooltip(tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Dava96 <https://github.com/Dava96>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum RunecraftingAltarLocation
|
||||
{
|
||||
AIR_ALTAR("Air Altar", 1, new WorldPoint(2985, 3293, 0), "air_altar_icon.png"),
|
||||
MIND_ALTAR("Mind Altar", 2, new WorldPoint(2982, 3514, 0), "mind_altar_icon.png"),
|
||||
WATER_ALTAR("Water Altar", 5, new WorldPoint(3185, 3165, 0), "water_altar_icon.png"),
|
||||
EARTH_ALTAR("Earth Altar", 9, new WorldPoint(3306, 3474, 0), "earth_altar_icon.png"),
|
||||
FIRE_ALTAR("Fire Altar", 14, new WorldPoint(3313, 3255, 0), "fire_altar_icon.png"),
|
||||
BODY_ALTAR("Body Altar", 20, new WorldPoint(3053, 3445, 0), "body_altar_icon.png"),
|
||||
COSMIC_ALTAR("Cosmic Altar", 27, new WorldPoint(2408, 4377, 0), "cosmic_altar_icon.png"),
|
||||
CHAOS_ALTAR("Chaos Altar", 35, new WorldPoint(3060, 3591, 0), "chaos_altar_icon.png"),
|
||||
ASTRAL_ALTAR("Astral Altar", 40, new WorldPoint(2158, 3864, 0), "astral_altar_icon.png"),
|
||||
NATURE_ALTAR("Nature Altar", 44, new WorldPoint(2869, 3019, 0), "nature_altar_icon.png"),
|
||||
LAW_ALTAR("Law Altar", 54, new WorldPoint(2858, 3381, 0), "law_altar_icon.png"),
|
||||
DEATH_ALTAR("Death Altar", 65, new WorldPoint(1860, 4639, 0), "death_altar_icon.png"),
|
||||
BLOOD_ALTAR("Blood Altar", 77, new WorldPoint(1716, 3827, 0), "blood_altar_icon.png"),
|
||||
SOUL_ALTAR("Soul Altar", 90, new WorldPoint(1814, 3856, 0), "soul_altar_icon.png"),
|
||||
WRATH_ALTAR("Wrath Altar", 95, new WorldPoint(2446, 2825, 0), "wrath_altar_icon.png");
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
private final int levelReq;
|
||||
private final String iconPath;
|
||||
|
||||
RunecraftingAltarLocation(String description, int level, WorldPoint location, String iconPath)
|
||||
{
|
||||
this.tooltip = description + " - Level " + level;
|
||||
this.location = location;
|
||||
this.levelReq = level;
|
||||
this.iconPath = iconPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Dava96 <https://github.com/Dava96>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
class RunecraftingAltarPoint extends WorldMapPoint
|
||||
{
|
||||
RunecraftingAltarPoint(RunecraftingAltarLocation point)
|
||||
{
|
||||
super(point.getLocation(), WorldMapPlugin.BLANK_ICON);
|
||||
setImage(ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, point.getIconPath()));
|
||||
setTooltip(point.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@Getter
|
||||
enum TeleportLocationData
|
||||
{
|
||||
VARROCK(TeleportType.NORMAL_MAGIC, "Varrock", 25, new WorldPoint(3213, 3424, 0), "varrock_teleport_icon.png"),
|
||||
VARROCK_GE(TeleportType.NORMAL_MAGIC, "Varrock GE", 25, new WorldPoint(3164, 3478, 0), "varrock_teleport_icon.png"),
|
||||
LUMBRIDGE(TeleportType.NORMAL_MAGIC, "Lumbridge", 31, new WorldPoint(3222, 3218, 0), "lumbridge_teleport_icon.png"),
|
||||
FALADOR(TeleportType.NORMAL_MAGIC, "Falador", 37, new WorldPoint(2965, 3381, 0), "falador_teleport_icon.png"),
|
||||
CAMELOT(TeleportType.NORMAL_MAGIC, "Camelot", 45, new WorldPoint(2757, 3477, 0), "camelot_teleport_icon.png"),
|
||||
CAMELOT_BANK(TeleportType.NORMAL_MAGIC, "Camelot Bank", 45, new WorldPoint(2726, 3485, 0), "camelot_teleport_icon.png"),
|
||||
ARDOUGNE(TeleportType.NORMAL_MAGIC, "Ardougne", 51, new WorldPoint(2664, 3306, 0), "ardougne_teleport_icon.png"),
|
||||
WATCHTOWER(TeleportType.NORMAL_MAGIC, "Watchtower", 58, new WorldPoint(2547, 3114, 0), "watchtower_teleport_icon.png"),
|
||||
WATCHTOWER_YANILLE(TeleportType.NORMAL_MAGIC, "Watchtower Yanille", 58, new WorldPoint(2584, 3097, 0), "watchtower_teleport_icon.png"),
|
||||
TROLLHEIM(TeleportType.NORMAL_MAGIC, "Trollheim", 61, new WorldPoint(2891, 3678, 0), "trollheim_teleport_icon.png"),
|
||||
APE_ATOLL(TeleportType.NORMAL_MAGIC, "Ape Atoll", 64, new WorldPoint(2796, 2791, 0), "ape_atoll_teleport_icon.png"),
|
||||
KOUREND(TeleportType.NORMAL_MAGIC, "Kourend", 69, new WorldPoint(1643, 3672, 0), "kourend_teleport_icon.png"),
|
||||
PADDEWWA(TeleportType.ANCIENT_MAGICKS, "Paddewwa", 54, new WorldPoint(3097, 9880, 0), "paddewwa_teleport_icon.png"),
|
||||
SENNTISTEN(TeleportType.ANCIENT_MAGICKS, "Senntisten", 60, new WorldPoint(3319, 3336, 0), "senntisten_teleport_icon.png"),
|
||||
KHARYRLL(TeleportType.ANCIENT_MAGICKS, "Kharyrll", 66, new WorldPoint(3494, 3473, 0), "kharyrll_teleport_icon.png"),
|
||||
LASSAR(TeleportType.ANCIENT_MAGICKS, "Lassar", 72, new WorldPoint(3002, 3472, 0), "lassar_teleport_icon.png"),
|
||||
DAREEYAK(TeleportType.ANCIENT_MAGICKS, "Dareeyak", 78, new WorldPoint(2969, 3695, 0), "dareeyak_teleport_icon.png"),
|
||||
CARRALLANGAR(TeleportType.ANCIENT_MAGICKS, "Carrallangar", 84, new WorldPoint(3157, 3667, 0), "carrallangar_teleport_icon.png"),
|
||||
ANNAKARL(TeleportType.ANCIENT_MAGICKS, "Annakarl", 90, new WorldPoint(3288, 3888, 0), "annakarl_teleport_icon.png"),
|
||||
GHORROCK(TeleportType.ANCIENT_MAGICKS, "Ghorrock", 96, new WorldPoint(2977, 3872, 0), "ghorrock_teleport_icon.png"),
|
||||
MOONCLAN(TeleportType.LUNAR_MAGIC, "Moonclan", 69, new WorldPoint(2113, 3915, 0), "moonclan_teleport_icon.png"),
|
||||
OURANIA(TeleportType.LUNAR_MAGIC, "Ourania", 71, new WorldPoint(2468, 3246, 0), "ourania_teleport_icon.png"),
|
||||
WATERBIRTH(TeleportType.LUNAR_MAGIC, "Waterbirth", 72, new WorldPoint(2546, 3755, 0), "waterbirth_teleport_icon.png"),
|
||||
BARBARIAN(TeleportType.LUNAR_MAGIC, "Barbarian", 75, new WorldPoint(2543, 3568, 0), "barbarian_teleport_icon.png"),
|
||||
KHAZARD(TeleportType.LUNAR_MAGIC, "Khazard", 78, new WorldPoint(2636, 3167, 0), "khazard_teleport_icon.png"),
|
||||
FISHING_GUILD(TeleportType.LUNAR_MAGIC, "Fishing Guild", 85, new WorldPoint(2612, 3391, 0), "fishing_guild_teleport_icon.png"),
|
||||
CATHERBY(TeleportType.LUNAR_MAGIC, "Catherby", 87, new WorldPoint(2802, 3449, 0), "catherby_teleport_icon.png"),
|
||||
ICE_PLATEAU(TeleportType.LUNAR_MAGIC, "Ice Plateau", 89, new WorldPoint(2973, 3939, 0), "ice_plateau_teleport_icon.png"),
|
||||
LUMBRIDGE_GRAVEYARD(TeleportType.ARCEUUS_MAGIC, "Lumbridge Graveyard", 6, new WorldPoint(3241, 3194, 0), "lumbridge_graveyard_teleport_icon.png"),
|
||||
DRAYNOR_MANOR(TeleportType.ARCEUUS_MAGIC, "Draynor Manor", 17, new WorldPoint(3108, 3352, 0), "draynor_manor_teleport_icon.png"),
|
||||
BATTLEFRONT(TeleportType.ARCEUUS_MAGIC, "Battlefront", 23, new WorldPoint(1349, 3739, 0), "battlefront_teleport_icon.png"),
|
||||
MIND_ALTAR(TeleportType.ARCEUUS_MAGIC, "Mind Altar", 28, new WorldPoint(2979, 3509, 0), "mind_altar_teleport_icon.png"),
|
||||
SALVE_GRAVEYARD(TeleportType.ARCEUUS_MAGIC, "Salve Graveyard", 40, new WorldPoint(3433, 3461, 0), "salve_graveyard_teleport_icon.png"),
|
||||
FENKENSTRAINS_CASTLE(TeleportType.ARCEUUS_MAGIC, "Fenkenstrain's Castle", 48, new WorldPoint(3548, 3528, 0), "fenkenstrains_castle_teleport_icon.png"),
|
||||
WEST_ARDOUGNE(TeleportType.ARCEUUS_MAGIC, "West Ardougne", 61, new WorldPoint(2500, 3291, 0), "west_ardougne_teleport_icon.png"),
|
||||
HARMONY_ISLAND(TeleportType.ARCEUUS_MAGIC, "Harmony Island", 65, new WorldPoint(3797, 2866, 0), "harmony_island_teleport_icon.png"),
|
||||
CEMETERY(TeleportType.ARCEUUS_MAGIC, "Cemetery", 71, new WorldPoint(2978, 3763, 0), "cemetery_teleport_icon.png"),
|
||||
BARROWS(TeleportType.ARCEUUS_MAGIC, "Barrows", 83, new WorldPoint(3565, 3315, 0), "barrows_teleport_icon.png"),
|
||||
APE_ATOLL_ARCEUUS(TeleportType.ARCEUUS_MAGIC, "Ape Atoll", 90, new WorldPoint(2770, 2703, 0), "ape_atoll_teleport_icon_arceuus.png"),
|
||||
|
||||
// Jewellery
|
||||
BARBARIAN_ASSAULT(TeleportType.JEWELLERY, "Games Necklace" , "Barbarian Assault", new WorldPoint(2520, 3571, 0), "games_necklace_teleport_icon.png"),
|
||||
BURTHORPE_GAMES_ROOM(TeleportType.JEWELLERY, "Games Necklace" , "Burthorpe Games Room", new WorldPoint(2898, 3554, 0), "games_necklace_teleport_icon.png"),
|
||||
TEARS_OF_GUTHIX(TeleportType.JEWELLERY, "Games Necklace" , "Tears of Guthix", new WorldPoint(3245, 9500, 0), "games_necklace_teleport_icon.png"),
|
||||
CORPOREAL_BEAST(TeleportType.JEWELLERY, "Games Necklace" , "Corporeal Beast", new WorldPoint(2967, 4384, 0), "games_necklace_teleport_icon.png"),
|
||||
WINTERTODT_CAMP(TeleportType.JEWELLERY, "Games Necklace" , "Wintertodt Camp", new WorldPoint(1624, 3938, 0), "games_necklace_teleport_icon.png"),
|
||||
DUEL_ARENA(TeleportType.JEWELLERY, "Ring of Dueling" , "Duel Arena", new WorldPoint(3315, 3235, 0), "ring_of_dueling_teleport_icon.png"),
|
||||
FEROX_ENCLAVE(TeleportType.JEWELLERY, "Ring of Dueling" , "Ferox Enclave", new WorldPoint(3151, 3636, 0), "ring_of_dueling_teleport_icon.png"),
|
||||
CASTLE_WARS(TeleportType.JEWELLERY, "Ring of Dueling" , "Castle Wars", new WorldPoint(2441, 3091, 0), "ring_of_dueling_teleport_icon.png"),
|
||||
WARRIORS_GUILD(TeleportType.JEWELLERY, "Combat Bracelet" , "Warriors' Guild", new WorldPoint(2883, 3549, 0), "combat_bracelet_teleport_icon.png"),
|
||||
CHAMPIONS_GUILD(TeleportType.JEWELLERY, "Combat Bracelet" , "Champions' Guild", new WorldPoint(3189, 3368, 0), "combat_bracelet_teleport_icon.png"),
|
||||
EDGEVILLE_MONASTERY(TeleportType.JEWELLERY, "Combat Bracelet" , "Edgeville Monastery", new WorldPoint(3053, 3487, 0), "combat_bracelet_teleport_icon.png"),
|
||||
RANGING_GUILD(TeleportType.JEWELLERY, "Combat Bracelet" , "Ranging Guild", new WorldPoint(2654, 3441, 0), "combat_bracelet_teleport_icon.png"),
|
||||
FISHING_GUILD_NECK(TeleportType.JEWELLERY, "Skills Necklace" , "Fishing Guild", new WorldPoint(2613, 3390, 0), "skills_necklace_teleport_icon.png"),
|
||||
MINING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Mining Guild", new WorldPoint(3049, 9762, 0), "skills_necklace_teleport_icon.png"),
|
||||
CRAFTING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Crafting Guild", new WorldPoint(2934, 3294, 0), "skills_necklace_teleport_icon.png"),
|
||||
COOKING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Cooking Guild", new WorldPoint(3145, 3438, 0), "skills_necklace_teleport_icon.png"),
|
||||
WOODCUTTING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Woodcutting Guild", new WorldPoint(1662, 3505, 0), "skills_necklace_teleport_icon.png"),
|
||||
FARMING_GUILD(TeleportType.JEWELLERY, "Skills Necklace" , "Farming Guild", new WorldPoint(1249, 3717, 0), "skills_necklace_teleport_icon.png"),
|
||||
EDGEVILLE(TeleportType.JEWELLERY, "Amulet of Glory" , "Edgeville", new WorldPoint(3087, 3496, 0), "amulet_of_glory_teleport_icon.png"),
|
||||
KARAMJA(TeleportType.JEWELLERY, "Amulet of Glory" , "Karamja", new WorldPoint(2918, 3176, 0), "amulet_of_glory_teleport_icon.png"),
|
||||
DRAYNOR_VILLAGE(TeleportType.JEWELLERY, "Amulet of Glory" , "Draynor Village", new WorldPoint(3105, 3251, 0), "amulet_of_glory_teleport_icon.png"),
|
||||
AL_KHARID(TeleportType.JEWELLERY, "Amulet of Glory" , "Al-Kharid", new WorldPoint(3293, 3163, 0), "amulet_of_glory_teleport_icon.png"),
|
||||
MISCELLANIA(TeleportType.JEWELLERY, "Ring of Wealth" , "Miscellania", new WorldPoint(2535, 3862, 0), "ring_of_wealth_teleport_icon.png"),
|
||||
GRAND_EXCHANGE(TeleportType.JEWELLERY, "Ring of Wealth" , "Grand Exchange", new WorldPoint(3162, 3480, 0), "ring_of_wealth_teleport_icon.png"),
|
||||
FALADOR_PARK(TeleportType.JEWELLERY, "Ring of Wealth" , "Falador Park", new WorldPoint(2995, 3375, 0), "ring_of_wealth_teleport_icon.png"),
|
||||
DONDAKAN(TeleportType.JEWELLERY, "Ring of Wealth" , "Dondakan", new WorldPoint(2831, 10165, 0), "ring_of_wealth_teleport_icon.png"),
|
||||
SLAYER_TOWER(TeleportType.JEWELLERY, "Slayer Ring" , "Slayer Tower", new WorldPoint(3423, 3536, 0), "slayer_ring_teleport_icon.png"),
|
||||
FREMENNIK_SLAYER_DUNGEON(TeleportType.JEWELLERY, "Slayer Ring" , "Fremennik Slayer Dungeon", new WorldPoint(2800, 9998, 0), "slayer_ring_teleport_icon.png"),
|
||||
FREMENNIK_SLAYER_DUNGEON_OUTSIDE(TeleportType.JEWELLERY, "Slayer Ring" , "Fremennik Slayer Dungeon (inside)", new WorldPoint(2800, 3615, 0), "slayer_ring_teleport_icon.png"),
|
||||
TARNS_LAIR(TeleportType.JEWELLERY, "Slayer Ring" , "Tarn's Lair", new WorldPoint(3187, 4601, 0), "slayer_ring_teleport_icon.png"),
|
||||
STRONGHOLD_SLAYER_CAVE(TeleportType.JEWELLERY, "Slayer Ring" , "Stronghold Slayer Cave", new WorldPoint(2433, 3421, 0), "slayer_ring_teleport_icon.png"),
|
||||
DARK_BEASTS(TeleportType.JEWELLERY, "Slayer Ring" , "Dark Beasts", new WorldPoint(2028, 4638, 0), "slayer_ring_teleport_icon.png"),
|
||||
DIGSITE(TeleportType.JEWELLERY, "Digsite Pendant" , "Digsite", new WorldPoint(3339, 3445, 0), "digsite_pendant_teleport_icon.png"),
|
||||
HOUSE_ON_THE_HILL(TeleportType.JEWELLERY, "Digsite Pendant" , "House on the Hill", new WorldPoint(3763, 3869, 0), "digsite_pendant_teleport_icon.png"),
|
||||
LITHKREN(TeleportType.JEWELLERY, "Digsite Pendant" , "Lithkren", new WorldPoint(3547, 10456, 0), "digsite_pendant_teleport_icon.png"),
|
||||
WIZARDS_TOWER(TeleportType.JEWELLERY, "Necklace of Passage" , "Wizards' Tower", new WorldPoint(3114, 3181, 0), "necklace_of_passage_teleport_icon.png"),
|
||||
JORRALS_OUTPOST(TeleportType.JEWELLERY, "Necklace of Passage" , "Jorral's Outpost", new WorldPoint(2431, 3348, 0), "necklace_of_passage_teleport_icon.png"),
|
||||
DESERT_EAGLE_STATION(TeleportType.JEWELLERY, "Necklace of Passage" , "Desert eagle station of the eagle transport system", new WorldPoint(3406, 3157, 0), "necklace_of_passage_teleport_icon.png"),
|
||||
CHAOS_TEMPLE(TeleportType.JEWELLERY, "Burning Amulet" , "Chaos Temple (lvl 15)", new WorldPoint(3234, 3637, 0), "burning_amulet_teleport_icon.png"),
|
||||
BANDIT_CAMP(TeleportType.JEWELLERY, "Burning Amulet" , "Bandit Camp (lvl 17)", new WorldPoint(3038, 3651, 0), "burning_amulet_teleport_icon.png"),
|
||||
LAVA_MAZE(TeleportType.JEWELLERY, "Burning Amulet" , "Lava Maze (lvl 41)", new WorldPoint(3028, 3840, 0), "burning_amulet_teleport_icon.png"),
|
||||
|
||||
// Misc
|
||||
XERICS_LOOKOUT(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Lookout", new WorldPoint(1576, 3528, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_GLADE(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Glade", new WorldPoint(1754, 3564, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_INFERNO(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Inferno", new WorldPoint(1504, 3819, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_HEART(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Heart", new WorldPoint(1641, 3670, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_HONOUR(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Honour", new WorldPoint(1254, 3559, 0), "xerics_talisman_teleport_icon.png"),
|
||||
STRONGHOLD_OF_SECURITY(TeleportType.OTHER, "Skull Sceptre", "Stronghold of Security", new WorldPoint(3081, 3421, 0), "skull_sceptre_teleport_icon.png"),
|
||||
MYTHS_GUILD(TeleportType.OTHER, "Mythical Cape", "Myth's Guild", new WorldPoint(2458, 2851, 0), "mythical_cape_teleport_icon.png"),
|
||||
ECTOFUNTUS(TeleportType.OTHER, "Ectophial", "Ectofuntus", new WorldPoint(3660, 3522, 0), "ectophial_teleport_icon.png"),
|
||||
CHAMPIONS_GUILD_CHRONICLE(TeleportType.OTHER, "Chronicle", "Champions' Guild", new WorldPoint(3202, 3357, 0), "chronicle_teleport_icon.png"),
|
||||
GRAND_TREE(TeleportType.OTHER, "Royal Seed Pod", "Grand Tree", new WorldPoint(2465, 3495, 0), "royal_seed_pod_teleport_icon.png"),
|
||||
RELLEKKKA_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Rellekka", new WorldPoint(2664, 3643, 0), "enchanted_lyre_teleport_icon.png"),
|
||||
WATERBIRTH_ISLAND_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Waterbirth Island", new WorldPoint(2550, 3756, 0), "enchanted_lyre_teleport_icon.png"),
|
||||
NEITIZNOT_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Neitiznot", new WorldPoint(2336, 3801, 0), "enchanted_lyre_teleport_icon.png"),
|
||||
JATIZSO_LYRE(TeleportType.OTHER, "Enchanted Lyre", "Jatizso", new WorldPoint(2409, 3809, 0), "enchanted_lyre_teleport_icon.png"),
|
||||
WEISS_ICY_BASALT(TeleportType.OTHER, "Icy Basalt", "Weiss", new WorldPoint(2846, 3940, 0), "icy_basalt_teleport_icon.png"),
|
||||
TROLL_STRONGHOLD_STONY_BASALT(TeleportType.OTHER, "Stony Basalt", "Troll Stronghold (with 73 Agility)", new WorldPoint(2838, 3693, 0), "stony_basalt_teleport_icon.png"),
|
||||
TROLL_STRONGHOLD_STONY_BASALT_OUTSIDE(TeleportType.OTHER, "Stony Basalt", "Troll Stronghold", new WorldPoint(2844, 3693, 0), "stony_basalt_teleport_icon.png"),
|
||||
KHAREDSTS_MEMOIRS_HOSIDIUS(TeleportType.OTHER, "Kharedst's Memoirs", "Lunch by the Lancalliums (Hosidius)", new WorldPoint(1713, 3612, 0), "kharedsts_memoirs_teleport_icon.png"),
|
||||
KHAREDSTS_MEMOIRS_PISCARILIUS(TeleportType.OTHER, "Kharedst's Memoirs", "The Fisher's Flute (Piscarilius)", new WorldPoint(1802, 3748, 0), "kharedsts_memoirs_teleport_icon.png"),
|
||||
KHAREDSTS_MEMOIRS_SHAYZIEN(TeleportType.OTHER, "Kharedst's Memoirs", "History and Hearsay (Shayzien)", new WorldPoint(1476, 3580, 0), "kharedsts_memoirs_teleport_icon.png"),
|
||||
KHAREDSTS_MEMOIRS_LOVAKENGJ(TeleportType.OTHER, "Kharedst's Memoirs", "Jewelry of Jubilation (Lovakengj)", new WorldPoint(1544, 3762, 0), "kharedsts_memoirs_teleport_icon.png"),
|
||||
KHAREDSTS_MEMOIRS_ARCEUUS(TeleportType.OTHER, "Kharedst's Memoirs", "A Dark Disposition (Arceuus)", new WorldPoint(1680, 3746, 0), "kharedsts_memoirs_teleport_icon.png"),
|
||||
PHARAOHS_SCEPTRE_JALSAVRAH(TeleportType.OTHER, "Pharaoh's Sceptre", "Jalsavrah (Pyramid Plunder)", new WorldPoint(3288, 2795, 0), "pharaohs_sceptre_teleport_icon.png"),
|
||||
PHARAOHS_SCEPTRE_JALEUSTROPHOS(TeleportType.OTHER, "Pharaoh's Sceptre", "Jaleustrophos (Agility Pyramid)", new WorldPoint(3341, 2827, 0), "pharaohs_sceptre_teleport_icon.png"),
|
||||
PHARAOHS_SCEPTRE_JALDRAOCHT(TeleportType.OTHER, "Pharaoh's Sceptre", "Jaldraocht (Desert Treasure Pyramid)", new WorldPoint(3232, 2897, 0), "pharaohs_sceptre_teleport_icon.png"),
|
||||
CAMULET_TEMPLE(TeleportType.OTHER, "Camulet", "Enakhra's Temple", new WorldPoint(3190, 2923, 0), "camulet_teleport_icon.png"),
|
||||
TELEPORT_CRYSTAL_LLETYA(TeleportType.OTHER, "Teleport crystal", "Lletya", new WorldPoint(2330, 3172, 0), "teleport_crystal_icon.png"),
|
||||
TELEPORT_CRYSTAL_PRIFDDINAS(TeleportType.OTHER, "Teleport crystal", "Prifddinas", new WorldPoint(3264, 6065, 0), "teleport_crystal_icon.png"),
|
||||
DRAKANS_MEDALLION_VER_SINHAZA(TeleportType.OTHER, "Drakan's medallion", "Ver Sinhaza", new WorldPoint(3649, 3230, 0), "drakans_medallion_teleport_icon.png"),
|
||||
DRAKANS_MEDALLION_DARKMEYER(TeleportType.OTHER, "Drakan's medallion", "Darkmeyer", new WorldPoint(3592, 3337, 0), "drakans_medallion_teleport_icon.png"),
|
||||
|
||||
// Wilderness
|
||||
OBELISK_13(TeleportType.OTHER, "Obelisk", "13", new WorldPoint(3156, 3620, 0), "obelisk_icon.png"),
|
||||
OBELISK_19(TeleportType.OTHER, "Obelisk", "19", new WorldPoint(3227, 3667, 0), "obelisk_icon.png"),
|
||||
OBELISK_27(TeleportType.OTHER, "Obelisk", "27", new WorldPoint(3035, 3732, 0), "obelisk_icon.png"),
|
||||
OBELISK_35(TeleportType.OTHER, "Obelisk", "35", new WorldPoint(3106, 3794, 0), "obelisk_icon.png"),
|
||||
OBELISK_44(TeleportType.OTHER, "Obelisk", "44", new WorldPoint(2980, 3866, 0), "obelisk_icon.png"),
|
||||
OBELISK_50(TeleportType.OTHER, "Obelisk", "50", new WorldPoint(3307, 3916, 0), "obelisk_icon.png"),
|
||||
WILDERNESS_CRABS_TELEPORT(TeleportType.OTHER, "Wilderness crabs teleport", new WorldPoint(3348, 3783, 0), "wilderness_crabs_teleport_icon.png"),
|
||||
CANOE_WILDERNESS(TeleportType.OTHER, "Canoe (No departure)", "35", new WorldPoint(3141, 3796, 0), "transportation_icon.png"),
|
||||
|
||||
// Achievement Diary
|
||||
ARDOUGNE_CLOAK_MONASTERY(TeleportType.OTHER, "Ardougne Cloak", "Monastery", new WorldPoint(2606, 3222, 0), "ardougne_cloak_icon.png"),
|
||||
ARDOUGNE_CLOAK_FARM(TeleportType.OTHER, "Ardougne Cloak", "Farm", new WorldPoint(2673, 3375, 0), "ardougne_cloak_icon.png"),
|
||||
EXPLORERS_RING(TeleportType.OTHER, "Explorer's Ring", new WorldPoint(3052, 3292, 0), "explorers_ring_icon.png"),
|
||||
KARAMJA_GLOVES_GEM_MINE(TeleportType.OTHER, "Karamja Gloves", "Gem Mine (Underground)", new WorldPoint(2827, 2997, 0), "karamja_gloves_icon.png"),
|
||||
KARAMJA_GLOVES_DURADEL(TeleportType.OTHER, "Karamja Gloves", "Duradel", new WorldPoint(2870, 2981, 0), "karamja_gloves_icon.png"),
|
||||
DESERT_AMULET_NARDAH(TeleportType.OTHER, "Desert Amulet", "Nardah", new WorldPoint(3425, 2928, 0), "desert_amulet_icon.png"),
|
||||
DESERT_AMULKT_KALPHITE_CAVE(TeleportType.OTHER, "Desert Amulet", "Kalphite Cave", new WorldPoint(3322, 3122, 0), "desert_amulet_icon.png"),
|
||||
MORYTANIA_LEGS_SLIME_PIT(TeleportType.OTHER, "Morytania Legs", "Slime Pit (Underground)", new WorldPoint(3654, 3516, 0), "morytania_legs_icon.png"),
|
||||
MORYTANIA_LEGS_BURGH_DE_ROTT(TeleportType.OTHER, "Morytania Legs", "Burgh de Rott", new WorldPoint(3482, 3231, 0), "morytania_legs_icon.png"),
|
||||
FREMENNIK_SEA_BOOTS(TeleportType.OTHER, "Fremennik Sea Boots", new WorldPoint(2640, 3675, 0), "fremennik_boots_icon.png"),
|
||||
KANDARIN_HEADGEAR(TeleportType.OTHER, "Kandarin Headgear", new WorldPoint(2729, 3411, 0), "kandarin_headgear_icon.png"),
|
||||
WILDERNESS_SWORD(TeleportType.OTHER, "Wilderness Sword", new WorldPoint(3377, 3891, 0), "wilderness_sword_icon.png"),
|
||||
WESTERN_BANNER(TeleportType.OTHER, "Western Banner", new WorldPoint(2329, 3685, 0), "western_banner_icon.png"),
|
||||
RADAS_BLESSING_MOUNT_KARUULM(TeleportType.OTHER, "Rada's Blessing", new WorldPoint(1311, 3795, 0), "radas_blessing_icon.png"),
|
||||
RADAS_BLESSING_WOODLANG(TeleportType.OTHER, "Rada's Blessing", new WorldPoint(1553, 3454, 0), "radas_blessing_icon.png"),
|
||||
|
||||
// Scrolls
|
||||
DIGSITE_SCROLL(TeleportType.SCROLL, "Digsite Teleport", new WorldPoint(3324, 3412, 0), "scroll_teleport_icon.png"),
|
||||
IORWERTH_CAMP_SCROLL(TeleportType.SCROLL, "Iorwerth Camp Teleport", new WorldPoint(2193, 3257, 0), "scroll_teleport_icon.png"),
|
||||
FELDIP_HILLS_SCROLL(TeleportType.SCROLL, "Feldip Hills Teleport", new WorldPoint(2542, 2925, 0), "scroll_teleport_icon.png"),
|
||||
LUMBERYARD_SCROLL(TeleportType.SCROLL, "Lumberyard Teleport", new WorldPoint(3303, 3487, 0), "scroll_teleport_icon.png"),
|
||||
LUNAR_ISLE_SCROLL(TeleportType.SCROLL, "Lunar Isle Teleport", new WorldPoint(2093, 3912, 0), "scroll_teleport_icon.png"),
|
||||
MORTTON_SCROLL(TeleportType.SCROLL, "Mort'ton", new WorldPoint(3489, 3288, 0), "scroll_teleport_icon.png"),
|
||||
MOS_LEHARMLESS_SCROLL(TeleportType.SCROLL, "Mos Le'Harmless Teleport", new WorldPoint(3701, 2996, 0), "scroll_teleport_icon.png"),
|
||||
NARDAH_SCROLL(TeleportType.SCROLL, "Nardah Teleport", new WorldPoint(3421, 2917, 0), "scroll_teleport_icon.png"),
|
||||
PEST_CONTROL_SCROLL(TeleportType.SCROLL, "Pest Control Teleport", new WorldPoint(2657, 2660, 0), "scroll_teleport_icon.png"),
|
||||
PISCATORIS_SCROLL(TeleportType.SCROLL, "Piscatoris Teleport", new WorldPoint(2339, 3648, 0), "scroll_teleport_icon.png"),
|
||||
TAI_BWO_WANNAI_SCROLL(TeleportType.SCROLL, "Tai Bwo Wannai Teleport", new WorldPoint(2788, 3066, 0), "scroll_teleport_icon.png"),
|
||||
ZULANDRA_SCROLL(TeleportType.SCROLL, "Zul-Andra Teleport", new WorldPoint(2197, 3056, 0), "scroll_teleport_icon.png"),
|
||||
KEY_MASTER_SCROLL(TeleportType.SCROLL, "Key Master Teleport", new WorldPoint(2686, 9882, 0), "scroll_teleport_icon.png"),
|
||||
REVENANT_CAVE_SCROLL(TeleportType.SCROLL, "Revenant Cave Teleport", new WorldPoint(3127, 3833, 0), "scroll_teleport_icon.png");
|
||||
|
||||
private final TeleportType type;
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
private final String iconPath;
|
||||
|
||||
TeleportLocationData(TeleportType type, String destination, int magicLevel, WorldPoint location, String iconPath)
|
||||
{
|
||||
this.type = type;
|
||||
this.tooltip = type.getPrefix() + " " + destination + " - lvl " + magicLevel;
|
||||
this.location = location;
|
||||
this.iconPath = iconPath;
|
||||
}
|
||||
|
||||
TeleportLocationData(TeleportType type, String item, String destination, WorldPoint location, String iconPath)
|
||||
{
|
||||
this.type = type;
|
||||
this.tooltip = item + " - " + destination;
|
||||
this.location = location;
|
||||
this.iconPath = iconPath;
|
||||
}
|
||||
|
||||
TeleportLocationData(TeleportType type, String item, WorldPoint location, String iconPath)
|
||||
{
|
||||
this.type = type;
|
||||
this.tooltip = item;
|
||||
this.location = location;
|
||||
this.iconPath = iconPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
class TeleportPoint extends WorldMapPoint
|
||||
{
|
||||
TeleportPoint(TeleportLocationData data)
|
||||
{
|
||||
super(data.getLocation(), WorldMapPlugin.BLANK_ICON);
|
||||
setTooltip(data.getTooltip());
|
||||
setImage(ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, data.getIconPath()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum TeleportType
|
||||
{
|
||||
NORMAL_MAGIC(""),
|
||||
ANCIENT_MAGICKS("Ancient - "),
|
||||
LUNAR_MAGIC("Lunar - "),
|
||||
ARCEUUS_MAGIC("Arceuus - "),
|
||||
JEWELLERY("Jewellery - "),
|
||||
SCROLL(""),
|
||||
OTHER("");
|
||||
|
||||
private String prefix;
|
||||
|
||||
TeleportType(String prefix)
|
||||
{
|
||||
this.prefix = prefix;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Kyle Sergio <https://github.com/ksergio39>
|
||||
* Copyright (c) 2019, Bryce Altomare <https://github.com/Twinkiel0ver>
|
||||
* Copyright (c) 2019, Kyle Stead <http://github.com/kyle1elyk>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
class TransportationPoint extends WorldMapPoint
|
||||
{
|
||||
TransportationPoint(TransportationPointLocation data, BufferedImage icon)
|
||||
{
|
||||
super(data.getLocation(), icon);
|
||||
final WorldPoint target = data.getTarget();
|
||||
if (target != null)
|
||||
{
|
||||
setTarget(target);
|
||||
setJumpOnClick(true);
|
||||
}
|
||||
setTooltip(data.getTooltip());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Kyle Sergio <https://github.com/ksergio39>
|
||||
* Copyright (c) 2019, Bryce Altomare <https://github.com/Twinkiel0ver>
|
||||
* Copyright (c) 2019, Kyle Stead <http://github.com/kyle1elyk>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
enum TransportationPointLocation
|
||||
{
|
||||
//Ships
|
||||
ARDOUGNE_TO_BRIMHAVEN("Ship to Brimhaven / Rimmington", new WorldPoint(2675, 3275, 0)),
|
||||
ARDOUGNE_TO_FISHINGPLAT("Ship to Fishing Platform", new WorldPoint(2722, 3304, 0), new WorldPoint(2779, 3271, 0)),
|
||||
BRIMHAVEN_TO_ARDOUGNE("Ship to Ardougne / Rimmington", new WorldPoint(2772, 3234, 0)),
|
||||
RIMMINGTON_TO_ARDOUGNE("Ship to Ardougne / Brimhaven", new WorldPoint(2915, 3224, 0)),
|
||||
CATHERBY_TO_KEEP_LE_FAYE("Ship to Keep Le Faye", new WorldPoint(2804, 3421, 0), new WorldPoint(2769, 3402, 0)),
|
||||
CORSAIR_TO_RIMMINGTON("Ship to Rimmington", new WorldPoint(2577, 2839, 0), new WorldPoint(2909, 3227, 0 )),
|
||||
DRAGONTOOTH_TO_PHASMATYS("Ship to Port Phasmatys", new WorldPoint(3791, 3561, 0), new WorldPoint(3703, 3487, 0)),
|
||||
DIGSITE_TO_FOSSIL("Ship to Fossil Island", new WorldPoint(3361, 3448, 0), new WorldPoint(3723, 3807, 0)),
|
||||
ENTRANA_TO_PORTSARIM("Ship to Port Sarim", new WorldPoint(2833, 3334, 0), new WorldPoint(3046, 3233, 0)),
|
||||
FISHINGPLAT_TO_ARDOUGNE("Ship to Ardougne", new WorldPoint(2779, 3271, 0), new WorldPoint(2722, 3304, 0)),
|
||||
HARMLESS_TO_PORT_PHASMATYS("Ship to Port Phasmatys", new WorldPoint(3682, 2951, 0), new WorldPoint(3709, 3497, 0)),
|
||||
ICEBERG_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2657, 3988, 0), new WorldPoint(2707, 3735, 0)),
|
||||
ISLAND_OF_STONE_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2470, 3994, 0), new WorldPoint(2621, 3692, 0)),
|
||||
ISLAND_TO_APE_ATOLL("Ship to Ape Atoll", new WorldPoint(2891, 2726, 0), new WorldPoint(2802, 2706, 0)),
|
||||
JATIZSO_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2420, 3780, 0), new WorldPoint(2639, 3710, 0)),
|
||||
KARAMJA_TO_PORT_SARIM("Ship to Port Sarim", new WorldPoint(2955, 3145, 0), new WorldPoint(3029, 3218, 0)),
|
||||
KARAMJA_TO_PORT_KHAZARD("Ship to Port Khazard", new WorldPoint(2763, 2957, 0), new WorldPoint(2653, 3166, 0)),
|
||||
LANDSEND_TO_PORTSARIM_PORTPISCARILIUS("Ship to Port Sarim/Port Piscarilius", new WorldPoint(1503, 3398, 0)),
|
||||
LUNAR_ISLE_TO_PIRATES_COVE("Ship to Pirates' Cove", new WorldPoint(2137, 3899, 0), new WorldPoint(2223, 3796, 0)),
|
||||
MISCELLANIA_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2579, 3846, 0), new WorldPoint(2627, 3692, 0)),
|
||||
NEITIZNOT_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2310, 3779, 0), new WorldPoint(2639, 3710, 0)),
|
||||
PESTCONTROL_TO_PORTSARIM("Ship to Port Sarim", new WorldPoint(2659, 2675, 0), new WorldPoint(3039, 3201, 0)),
|
||||
PIRATES_COVE_TO_LUNAR_ISLE("Ship to Lunar Isle", new WorldPoint(2223, 3796, 0), new WorldPoint(2137, 3899, 0)),
|
||||
PIRATES_COVE_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2212, 3794, 0), new WorldPoint(2620, 3695, 0)),
|
||||
PORT_PHASMATYS_TO_DRAGONTOOTH("Ship to Dragontooth Island", new WorldPoint(3703, 3487, 0), new WorldPoint(3791, 3561, 0)),
|
||||
PORT_PHASMATYS_TO_HARMLESS("Ship to Mos Le'Harmless", new WorldPoint(3709, 3497, 0), new WorldPoint(3682, 2951, 0)),
|
||||
PORT_PISCARILIUS_TO_PORTSARIM_LANDSEND("Ship to Port Sarim/Land's End", new WorldPoint(1823, 3692, 0)),
|
||||
PORTSARIM_TO_GREAT_KOUREND("Ship to Great Kourend", new WorldPoint(3054, 3244, 0), new WorldPoint(1823, 3692, 0)),
|
||||
PORTSARIM_TO_ENTRANA("Ship to Entrana", new WorldPoint(3046, 3233, 0), new WorldPoint(2833, 3334, 0)),
|
||||
PORTSARIM_TO_KARAMJA("Ship to Karamja", new WorldPoint(3029, 3218, 0), new WorldPoint(2955, 3144, 0)),
|
||||
PORTSARIM_TO_CRANDOR("Ship to Crandor", new WorldPoint(3045, 3205, 0), new WorldPoint(2839, 3261, 0)),
|
||||
PORTSARIM_TO_PEST_CONTROL("Ship to Pest Control", new WorldPoint(3039, 3201, 0), new WorldPoint(2659, 2675, 0)),
|
||||
RELLEKKA_TO_JATIZSO_NEITIZNOT("Ship to Jatizso/Neitiznot", new WorldPoint(2639, 3710, 0)),
|
||||
RELLEKKA_TO_MISCELLANIA("Ship to Miscellania", new WorldPoint(2627, 3692, 0), new WorldPoint(2579, 3846, 0)),
|
||||
RELLEKKA_TO_PIRATES_COVE("Ship to Pirates' Cove", new WorldPoint(2620, 3695, 0), new WorldPoint(2212, 3794, 0)),
|
||||
RELLEKKA_TO_WATERBIRTH("Ship to Waterbirth", new WorldPoint(2618, 3685, 0), new WorldPoint(2549, 3758, 0)),
|
||||
RELLEKKA_TO_WEISS_ICEBERG("Ship to Weiss/Iceberg", new WorldPoint(2707, 3735, 0)),
|
||||
RELLEKKA_TO_UNGAEL("Ship to Ungael", new WorldPoint(2638, 3698, 0), new WorldPoint(2276, 4034, 0)),
|
||||
RIMMINGTON_TO_CORSAIR_COVE("Ship to Corsair Cove", new WorldPoint(2909, 3227, 0 ), new WorldPoint(2577, 2839, 0)),
|
||||
WATERBIRTH_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2549, 3758, 0), new WorldPoint(2618, 3685, 0)),
|
||||
WEISS_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2847, 3967, 0), new WorldPoint(2707, 3735, 0)),
|
||||
UNGAEL_TO_RELLEKKA("Ship to Rellekka", new WorldPoint(2276, 4034, 0), new WorldPoint(2638, 3698, 0)),
|
||||
|
||||
//Row Boats
|
||||
ROW_BOAT_BATTLEFRONT("Rowboat to Molch/Molch Island/Shayzien", new WorldPoint(1383, 3663, 0)),
|
||||
ROW_BOAT_BRAIN_DEATH("Rowboat to Port Phasmatys", new WorldPoint(2161, 5117, 0), new WorldPoint(3680, 3538, 0)),
|
||||
ROW_BOAT_BURGH_DE_ROTT("Rowboat to Meiyerditch", new WorldPoint(3522, 3168, 0), new WorldPoint(3589, 3172, 0)),
|
||||
ROW_BOAT_CRABCLAW("Rowboat to Hosidius", new WorldPoint(1780, 3417, 0), new WorldPoint(1779, 3457, 0)),
|
||||
ROW_BOAT_DIVING_ISLAND("Rowboat to Barge/Camp/North of Island", new WorldPoint(3764, 3901, 0)),
|
||||
ROW_BOAT_FISHING_GUILD("Rowboat to Hemenster", new WorldPoint(2598, 3426, 0), new WorldPoint(2613, 3439, 0)),
|
||||
ROW_BOAT_GNOME_STRONGHOLD("Rowboat to Fishing Colony", new WorldPoint(2368, 3487, 0), new WorldPoint(2356, 3641, 0)),
|
||||
ROW_BOAT_FISHING_COLONY("Rowboat to Gnome Stronghold", new WorldPoint(2356, 3641, 0), new WorldPoint(2368, 3487, 0)),
|
||||
ROW_BOAT_HEMENSTER("Rowboat to Fishing Guild", new WorldPoint(2613, 3439, 0), new WorldPoint(2598, 3426, 0)),
|
||||
ROW_BOAT_HOSIDIUS("Rowboat to Crabclaw Isle", new WorldPoint(1779, 3457, 0), new WorldPoint(1780, 3417, 0)),
|
||||
ROW_BOAT_LITHKREN("Rowboat to Mushroom Forest", new WorldPoint(3582, 3973, 0), new WorldPoint(3659, 3849, 0)),
|
||||
ROW_BOAT_LUMBRIDGE("Rowboat to Misthalin Mystery", new WorldPoint(3238, 3141, 0)),
|
||||
ROW_BOAT_MOLCH("Rowboat to Molch Island/Shayzien/Battlefront", new WorldPoint(1343, 3646, 0)),
|
||||
ROW_BOAT_MOLCH_ISLAND("Rowboat to Molch/Shayzien/Battlefront", new WorldPoint(1368, 3641, 0)),
|
||||
ROW_BOAT_MORT("Rowboat to Mort Myre", new WorldPoint(3518, 3284, 0), new WorldPoint(3498, 3380, 0)),
|
||||
ROW_BOAT_MORT_SWAMP("Rowboat to Mort'ton", new WorldPoint(3498, 3380, 0), new WorldPoint(3518, 3284, 0)),
|
||||
ROW_BOAT_MUSEUM_CAMP("Rowboat to Barge/Digsite/North of Island", new WorldPoint(3723, 3807, 0)),
|
||||
ROW_BOAT_MUSHROOM_FOREST_WEST("Rowboat to Lithkren", new WorldPoint(3659, 3849, 0), new WorldPoint(3582, 3973, 0)),
|
||||
ROW_BOAT_MUSHROOM_FOREST_NE("Rowboat to Barge/Camp/Sea", new WorldPoint(3733, 3894, 0)),
|
||||
ROW_BOAT_PORT_PHASMATYS_NORTH("Rowboat to Slepe", new WorldPoint(3670, 3545, 0), new WorldPoint(3661, 3279, 0)),
|
||||
ROW_BOAT_PORT_PHASMATYS_EAST("Rowboat to Braindeath Island", new WorldPoint(3680, 3538, 0), new WorldPoint(2161, 5117, 0)),
|
||||
ROW_BOAT_SHAYZIEN("Rowboat to Molch/Molch Island/Battlefront", new WorldPoint(1405, 3612, 0)),
|
||||
ROW_BOAT_SLEPE("Rowboat to Port Phasmatys", new WorldPoint(3661, 3279, 0), new WorldPoint(3670, 3545, 0)),
|
||||
OGRE_BOAT_FELDIP("Ogre Boat to Karamja", new WorldPoint(2653, 2964, 0), new WorldPoint(2757, 3085, 0)),
|
||||
OGRE_BOAT_KARAMJA("Ogre Boat to Feldip", new WorldPoint(2757, 3085, 0), new WorldPoint(2653, 2964, 0)),
|
||||
|
||||
//Charter ships
|
||||
CHARTER_BRIMHAVEN("Charter Ship", new WorldPoint(2760, 3238, 0)),
|
||||
CHARTER_CATHERBY("Charter Ship", new WorldPoint(2791, 3415, 0)),
|
||||
CHARTER_CORSAIR_("Charter Ship", new WorldPoint(2589, 2851, 0)),
|
||||
CHARTER_KARAMJA_NORTH("Charter Ship", new WorldPoint(2954, 3158, 0)),
|
||||
CHARTER_KARAMJA_EAST("Charter Ship", new WorldPoint(2999, 3032, 0)),
|
||||
CHARTER_KHAZARD("Charter Ship", new WorldPoint(2673, 3143, 0)),
|
||||
CHARTER_MOSLE_HARMLESS("Charter Ship", new WorldPoint(3669, 2931, 0)),
|
||||
CHARTER_PORT_PHASMATYS("Charter Ship", new WorldPoint(3702, 3503, 0)),
|
||||
CHARTER_PORTSARIM("Charter Ship", new WorldPoint(3037, 3191, 0)),
|
||||
CHARTER_TYRAS("Charter Ship", new WorldPoint(2141, 3123, 0)),
|
||||
CHARTER_PRIFDDINAS("Charter Ship", new WorldPoint(2156, 3331, 0)),
|
||||
CHARTER_PRIFDDINAS_INSTANCE("Charter Ship", new WorldPoint(3180, 6083, 0)),
|
||||
|
||||
//Minecarts/Carts
|
||||
MINE_CART_ARCEUUS("Minecart", new WorldPoint(1673, 3832, 0)),
|
||||
MINE_CART_GRANDEXCHANGE("Minecart to Keldagrim", new WorldPoint(3139, 3504, 0)),
|
||||
MINE_CART_HOSIDIUS("Minecart", new WorldPoint(1656, 3542, 0)),
|
||||
MINE_CART_KELDAGRIM("Minecart", new WorldPoint(2908, 10170, 0)),
|
||||
MINE_CART_LOVAKENGJ("Minecart", new WorldPoint(1524, 3721, 0)),
|
||||
MINE_CART_PORT_PISCARILIUS("Minecart", new WorldPoint(1760, 3708, 0)),
|
||||
MINE_CART_QUIDAMORTEM("Minecart", new WorldPoint(1253, 3550, 0)),
|
||||
MINE_CART_SHAYZIEN("Minecart", new WorldPoint(1586, 3622, 0)),
|
||||
MINE_CART_TAVERLEY_UNDERGROUND("Minecart", new WorldPoint(2874, 9870, 0)),
|
||||
CART_TO_BRIMHAVEN("Cart to Brimhaven", new WorldPoint(2833, 2958, 0), new WorldPoint(2780, 3214, 0)),
|
||||
CART_TO_SHILO("Cart to Shilo", new WorldPoint(2780, 3214, 0), new WorldPoint(2833, 2958, 0)),
|
||||
|
||||
//Canoes
|
||||
CANOE_BARBVILLAGE("Canoe", new WorldPoint(3111, 3409, 0)),
|
||||
CANOE_CHAMPIONSGUILD("Canoe", new WorldPoint(3202, 3344, 0)),
|
||||
CANOE_EDGEVILLE("Canoe", new WorldPoint(3130, 3509, 0)),
|
||||
CANOE_LUMBRIDGE("Canoe", new WorldPoint(3241, 3238, 0)),
|
||||
CANOE_FEROXENCLAVE("Canoe", new WorldPoint(3155, 3630, 0)),
|
||||
|
||||
//Gnome Gliders
|
||||
GNOME_GLIDER_KHARID("Gnome Glider", new WorldPoint(3278, 3213, 0)),
|
||||
GNOME_GLIDER_APE_ATOLL("Gnome Glider", new WorldPoint(2712, 2804, 0)),
|
||||
GNOME_GLIDER_KARAMJA("Gnome Glider", new WorldPoint(2971, 2974, 0)),
|
||||
GNOME_GLIDER_FELDIP("Gnome Glider", new WorldPoint(2540, 2969, 0)),
|
||||
GNOME_GLIDER_GNOMESTRONGHOLD("Gnome Glider", new WorldPoint(2460, 3502, 0)),
|
||||
GNOME_GLIDER_WHITEWOLF("Gnome Glider", new WorldPoint(2845, 3501, 0)),
|
||||
|
||||
//Balloons
|
||||
BALLOON_VARROCK("Hot Air Balloon", new WorldPoint(3298, 3480, 0)),
|
||||
BALLOON_YANILLE("Hot Air Balloon", new WorldPoint(2458, 3108, 0)),
|
||||
BALLOON_GNOMESTRONGHOLD("Hot Air Balloon", new WorldPoint(2478, 3459, 0)),
|
||||
BALLOON_TAVERLEY("Hot Air Balloon", new WorldPoint(2936, 3422, 0)),
|
||||
BALLOON_FALADOR("Hot Air Balloon", new WorldPoint(2921, 3301, 0)),
|
||||
|
||||
//Spirit Tree
|
||||
SPIRITTREE_ARDOUGNE("Spirit Tree", new WorldPoint(2554, 3259, 0)),
|
||||
SPIRITTREE_CORSAIR("Spirit Tree", new WorldPoint(2485, 2850, 0)),
|
||||
SPIRITTREE_GNOMESTRONGHOLD("Spirit Tree", new WorldPoint(2459, 3446, 0)),
|
||||
SPIRITTREE_GNOMEVILLAGE("Spirit Tree", new WorldPoint(2538, 3166, 0)),
|
||||
SPIRITTREE_GRANDEXCHANGE("Spirit Tree", new WorldPoint(3184, 3510, 0)),
|
||||
SPIRITTREE_PRIFDDINAS("Spirit Tree", new WorldPoint(3274, 6124, 0)),
|
||||
|
||||
//Carpets
|
||||
CARPET_KHARID("Carpet to Bedabin/Pollnivneach/Uzer", new WorldPoint(3311, 3107, 0)),
|
||||
CARPET_BEDABIN("Carpet to Shantay Pass", new WorldPoint(3183, 3042, 0), new WorldPoint(3311, 3107, 0)),
|
||||
CARPET_POLLNIVNEACH_NORTH("Carpet to Shantay Pass", new WorldPoint(3351, 3001, 0), new WorldPoint(3311, 3107, 0)),
|
||||
CARPET_POLLNIVNEACH_SOUTH("Carpet to Nardah/Sophanem/Menaphos", new WorldPoint(3345, 2943, 0)),
|
||||
CARPET_NARDAH("Carpet to Pollnivneach", new WorldPoint(3399, 2916, 0), new WorldPoint(3345, 2943, 0)),
|
||||
CARPET_SOPHANEM("Carpet to Pollnivneach", new WorldPoint(3288, 2814, 0), new WorldPoint(3345, 2943, 0)),
|
||||
CARPET_MENAPHOS("Carpet to Pollnivneach", new WorldPoint(3244, 2812, 0), new WorldPoint(3345, 2943, 0)),
|
||||
CARPET_UZER("Carpet to Shantay Pass", new WorldPoint(3468, 3111, 0), new WorldPoint(3311, 3107, 0)),
|
||||
|
||||
//Teleports
|
||||
TELEPORT_ARCHIVE_FROM_ARCEUUS("Teleport to Library Archive", new WorldPoint(1623, 3808, 0)),
|
||||
TELEPORT_HARMLESS_FROM_HARMONY("Teleport to Mos Le'Harmless", new WorldPoint(3784, 2828, 0)),
|
||||
TELEPORT_RUNE_ARDOUGNE("Teleport to Rune Essence", new WorldPoint(2681, 3325, 0)),
|
||||
TELEPORT_RUNE_YANILLE("Teleport to Rune Essence", new WorldPoint(2592, 3089, 0)),
|
||||
TELEPORT_SORCERESS_GARDEN("Teleport to Sorceress's Garden", new WorldPoint(3320, 3141, 0)),
|
||||
TELEPORT_PRIFDDINAS_LIBRARY("Teleport to Prifddinas Library", new WorldPoint(3254, 6082, 2)),
|
||||
|
||||
//Other
|
||||
ALTER_KOUREND_UNDERGROUND("Altar to Skotizo", new WorldPoint(1662, 10047, 0)),
|
||||
FAIRY_RING_ZANARIS_TO_KHARID("Fairy Ring to Al Kharid", new WorldPoint(2483, 4471, 0)),
|
||||
FAIRY_RING_ZANARIS_TO_SHACK("Fairy Ring to Shack", new WorldPoint(2451, 4471, 0)),
|
||||
MOUNTAIN_GUIDE_QUIDAMORTEM("Mountain Guide", new WorldPoint(1275, 3559, 0)),
|
||||
MOUNTAIN_GUIDE_WALL("Mountain Guide", new WorldPoint(1400, 3538, 0)),
|
||||
MUSHTREE_MUSHROOM_FOREST("Mushtree", new WorldPoint(3674, 3871, 0)),
|
||||
MUSHTREE_TAR_SWAMP("Mushtree", new WorldPoint(3676, 3755, 0)),
|
||||
MUSHTREE_VERDANT_VALLEY("Mushtree", new WorldPoint(3757, 3756, 0)),
|
||||
MYTHS_GUILD_PORTAL("Portal to Guilds", new WorldPoint(2456, 2856, 0)),
|
||||
TRAIN_KELDAGRIM("Railway Station", new WorldPoint(2941, 10179, 0)),
|
||||
WILDERNESS_LEVER_ARDOUGNE("Wilderness Lever to Deserted Keep", new WorldPoint(2559, 3309, 0), new WorldPoint(3154, 3924, 0)),
|
||||
WILDERNESS_LEVER_EDGEVILLE("Wilderness Lever to Deserted Keep", new WorldPoint(3088, 3474, 0), new WorldPoint(3154, 3924, 0)),
|
||||
WILDERNESS_LEVER_WILDERNESS("Wilderness Lever to Ardougne/Edgeville", new WorldPoint(3154, 3924, 0));
|
||||
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
@Nullable
|
||||
private final WorldPoint target;
|
||||
|
||||
TransportationPointLocation(String tooltip, WorldPoint worldPoint)
|
||||
{
|
||||
this(tooltip, worldPoint, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(WorldMapPlugin.CONFIG_KEY)
|
||||
public interface WorldMapConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_FAIRY_RING_TOOLTIPS,
|
||||
name = "Show fairy ring codes in tooltip",
|
||||
description = "Display the code for fairy rings in the icon tooltip",
|
||||
position = 1
|
||||
)
|
||||
default boolean fairyRingTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_FAIRY_RING_ICON,
|
||||
name = "Show fairy ring travel icon",
|
||||
description = "Override the travel icon for fairy rings",
|
||||
position = 2
|
||||
)
|
||||
default boolean fairyRingIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_AGILITY_SHORTCUT_TOOLTIPS,
|
||||
name = "Show agility level requirement",
|
||||
description = "Display the required Agility level in the icon tooltip",
|
||||
position = 3
|
||||
)
|
||||
default boolean agilityShortcutTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_AGILITY_SHORTCUT_LEVEL_ICON,
|
||||
name = "Indicate inaccessible shortcuts",
|
||||
description = "Indicate shortcuts you do not have the level to use on the icon",
|
||||
position = 4
|
||||
)
|
||||
default boolean agilityShortcutLevelIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_AGILITY_COURSE_TOOLTIPS,
|
||||
name = "Show agility course in tooltip",
|
||||
description = "Displays the name of the agility course in the tooltip",
|
||||
position = 5
|
||||
)
|
||||
default boolean agilityCourseTooltip()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_AGILITY_COURSE_ROOFTOP_ICON,
|
||||
name = "Indicate rooftop courses",
|
||||
description = "Replace the agility icon with a mark of grace for rooftop courses",
|
||||
position = 6
|
||||
)
|
||||
default boolean agilityCourseRooftop()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_NORMAL_TELEPORT_ICON,
|
||||
name = "Show Standard Spellbook destinations",
|
||||
description = "Show icons at the destinations for teleports in the Standard Spellbook",
|
||||
position = 7
|
||||
)
|
||||
default boolean normalTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_MINIGAME_TOOLTIP,
|
||||
name = "Show minigame name in tooltip",
|
||||
description = "Display the name of the minigame in the icon tooltip",
|
||||
position = 8
|
||||
)
|
||||
default boolean minigameTooltip()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_ANCIENT_TELEPORT_ICON,
|
||||
name = "Show Ancient Magicks destinations",
|
||||
description = "Show icons at the destinations for teleports in the Ancient Spellbook",
|
||||
position = 9
|
||||
)
|
||||
default boolean ancientTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_LUNAR_TELEPORT_ICON,
|
||||
name = "Show Lunar Spellbook destinations",
|
||||
description = "Show icons at the destinations for teleports in the Lunar Spellbook",
|
||||
position = 10
|
||||
)
|
||||
default boolean lunarTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_ARCEUUS_TELEPORT_ICON,
|
||||
name = "Show Arceuus Spellbook destinations",
|
||||
description = "Show icons at the destinations for teleports in the Arceuus Spellbook",
|
||||
position = 11
|
||||
)
|
||||
default boolean arceuusTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_JEWELLERY_TELEPORT_ICON,
|
||||
name = "Show jewellery teleport locations",
|
||||
description = "Show icons at the destinations for teleports from jewellery",
|
||||
position = 12
|
||||
)
|
||||
default boolean jewelleryTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_SCROLL_TELEPORT_ICON,
|
||||
name = "Show teleport scroll locations",
|
||||
description = "Show icons at the destinations for teleports from scrolls",
|
||||
position = 13
|
||||
)
|
||||
default boolean scrollTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_MISC_TELEPORT_ICON,
|
||||
name = "Show misc teleport locations",
|
||||
description = "Show icons at the destinations for miscellaneous teleport items",
|
||||
position = 14
|
||||
)
|
||||
default boolean miscellaneousTeleportIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_QUEST_START_TOOLTIPS,
|
||||
name = "Show quest names and status",
|
||||
description = "Indicates the names of quests and shows completion status",
|
||||
position = 15
|
||||
)
|
||||
default boolean questStartTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_FARMING_PATCH_TOOLTIPS,
|
||||
name = "Show farming patch type",
|
||||
description = "Display the type of farming patches in the icon tooltip",
|
||||
position = 16
|
||||
)
|
||||
default boolean farmingPatchTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_RARE_TREE_TOOLTIPS,
|
||||
name = "Show rare tree type",
|
||||
description = "Display the type of rare tree in the icon tooltip",
|
||||
position = 17
|
||||
)
|
||||
default boolean rareTreeTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_RARE_TREE_LEVEL_ICON,
|
||||
name = "Indicate unavailable trees",
|
||||
description = "Indicate rare trees you do not have the level to cut on the icon",
|
||||
position = 18
|
||||
)
|
||||
default boolean rareTreeLevelIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_TRANSPORTATION_TELEPORT_TOOLTIPS,
|
||||
name = "Show transportation tooltips",
|
||||
description = "Indicates types and destinations of Transportation",
|
||||
position = 19
|
||||
)
|
||||
default boolean transportationTeleportTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_RUNECRAFTING_ALTAR_ICON,
|
||||
name = "Show runecrafting altar locations",
|
||||
description = "Show the icons of runecrafting altars",
|
||||
position = 20
|
||||
)
|
||||
default boolean runecraftingAltarIcon()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_MINING_SITE_TOOLTIPS,
|
||||
name = "Show mining site tooltips",
|
||||
description = "Indicates the ore available at mining sites",
|
||||
position = 21
|
||||
)
|
||||
default boolean miningSiteTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_DUNGEON_TOOLTIPS,
|
||||
name = "Show dungeon tooltips",
|
||||
description = "Indicates the names of dungeons",
|
||||
position = 22
|
||||
)
|
||||
default boolean dungeonTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_HUNTER_AREA_TOOLTIPS,
|
||||
name = "Show hunter area tooltips",
|
||||
description = "Indicates the creatures inside a hunting area",
|
||||
position = 23
|
||||
)
|
||||
default boolean hunterAreaTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_FISHING_SPOT_TOOLTIPS,
|
||||
name = "Show fishing spot tooltips",
|
||||
description = "Indicates the type of fish fishable at the fishing spot",
|
||||
position = 24
|
||||
)
|
||||
default boolean fishingSpotTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = WorldMapPlugin.CONFIG_KEY_KOUREND_TASK_TOOLTIPS,
|
||||
name = "Show Kourend task tooltips",
|
||||
description = "Indicates the task or unlock for Kourend Favour locations",
|
||||
position = 25
|
||||
)
|
||||
default boolean kourendTaskTooltips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Morgan Lewis <https://github.com/MESLewis>
|
||||
* 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 HOLDER 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.worldmap;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Arrays;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Quest;
|
||||
import net.runelite.api.QuestState;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.AgilityShortcut;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "World Map",
|
||||
description = "Enhance the world map to display additional information",
|
||||
tags = {"agility", "dungeon", "fairy", "farming", "rings", "teleports"}
|
||||
)
|
||||
public class WorldMapPlugin extends Plugin
|
||||
{
|
||||
static final BufferedImage BLANK_ICON;
|
||||
private static final BufferedImage FAIRY_TRAVEL_ICON;
|
||||
private static final BufferedImage NOPE_ICON;
|
||||
private static final BufferedImage NOT_STARTED_ICON;
|
||||
private static final BufferedImage STARTED_ICON;
|
||||
private static final BufferedImage FINISHED_ICON;
|
||||
private static final BufferedImage MINING_SITE_ICON;
|
||||
private static final BufferedImage ROOFTOP_COURSE_ICON;
|
||||
|
||||
static final String CONFIG_KEY = "worldmap";
|
||||
static final String CONFIG_KEY_FAIRY_RING_TOOLTIPS = "fairyRingTooltips";
|
||||
static final String CONFIG_KEY_FAIRY_RING_ICON = "fairyRingIcon";
|
||||
static final String CONFIG_KEY_AGILITY_SHORTCUT_TOOLTIPS = "agilityShortcutTooltips";
|
||||
static final String CONFIG_KEY_AGILITY_SHORTCUT_LEVEL_ICON = "agilityShortcutIcon";
|
||||
static final String CONFIG_KEY_AGILITY_COURSE_TOOLTIPS = "agilityCourseTooltips";
|
||||
static final String CONFIG_KEY_AGILITY_COURSE_ROOFTOP_ICON = "agilityCourseRooftopIcon";
|
||||
static final String CONFIG_KEY_NORMAL_TELEPORT_ICON = "standardSpellbookIcon";
|
||||
static final String CONFIG_KEY_ANCIENT_TELEPORT_ICON = "ancientSpellbookIcon";
|
||||
static final String CONFIG_KEY_LUNAR_TELEPORT_ICON = "lunarSpellbookIcon";
|
||||
static final String CONFIG_KEY_ARCEUUS_TELEPORT_ICON = "arceuusSpellbookIcon";
|
||||
static final String CONFIG_KEY_JEWELLERY_TELEPORT_ICON = "jewelleryIcon";
|
||||
static final String CONFIG_KEY_SCROLL_TELEPORT_ICON = "scrollIcon";
|
||||
static final String CONFIG_KEY_MISC_TELEPORT_ICON = "miscellaneousTeleportIcon";
|
||||
static final String CONFIG_KEY_QUEST_START_TOOLTIPS = "questStartTooltips";
|
||||
static final String CONFIG_KEY_MINIGAME_TOOLTIP = "minigameTooltip";
|
||||
static final String CONFIG_KEY_FARMING_PATCH_TOOLTIPS = "farmingpatchTooltips";
|
||||
static final String CONFIG_KEY_RARE_TREE_TOOLTIPS = "rareTreeTooltips";
|
||||
static final String CONFIG_KEY_RARE_TREE_LEVEL_ICON = "rareTreeIcon";
|
||||
static final String CONFIG_KEY_TRANSPORTATION_TELEPORT_TOOLTIPS = "transportationTooltips";
|
||||
static final String CONFIG_KEY_RUNECRAFTING_ALTAR_ICON = "runecraftingAltarIcon";
|
||||
static final String CONFIG_KEY_MINING_SITE_TOOLTIPS = "miningSiteTooltips";
|
||||
static final String CONFIG_KEY_DUNGEON_TOOLTIPS = "dungeonTooltips";
|
||||
static final String CONFIG_KEY_HUNTER_AREA_TOOLTIPS = "hunterAreaTooltips";
|
||||
static final String CONFIG_KEY_FISHING_SPOT_TOOLTIPS = "fishingSpotTooltips";
|
||||
static final String CONFIG_KEY_KOUREND_TASK_TOOLTIPS = "kourendTaskTooltips";
|
||||
|
||||
static
|
||||
{
|
||||
//A size of 17 gives us a buffer when triggering tooltips
|
||||
final int iconBufferSize = 17;
|
||||
|
||||
//Quest icons are a bit bigger.
|
||||
final int questIconBufferSize = 22;
|
||||
|
||||
BLANK_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
FAIRY_TRAVEL_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage fairyTravelIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "fairy_ring_travel.png");
|
||||
FAIRY_TRAVEL_ICON.getGraphics().drawImage(fairyTravelIcon, 1, 1, null);
|
||||
|
||||
NOPE_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage nopeImage = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "nope_icon.png");
|
||||
NOPE_ICON.getGraphics().drawImage(nopeImage, 1, 1, null);
|
||||
|
||||
NOT_STARTED_ICON = new BufferedImage(questIconBufferSize, questIconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage notStartedIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "quest_not_started_icon.png");
|
||||
NOT_STARTED_ICON.getGraphics().drawImage(notStartedIcon, 4, 4, null);
|
||||
|
||||
STARTED_ICON = new BufferedImage(questIconBufferSize, questIconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage startedIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "quest_started_icon.png");
|
||||
STARTED_ICON.getGraphics().drawImage(startedIcon, 4, 4, null);
|
||||
|
||||
FINISHED_ICON = new BufferedImage(questIconBufferSize, questIconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage finishedIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "quest_completed_icon.png");
|
||||
FINISHED_ICON.getGraphics().drawImage(finishedIcon, 4, 4, null);
|
||||
|
||||
MINING_SITE_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage miningSiteIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "mining_site_icon.png");
|
||||
MINING_SITE_ICON.getGraphics().drawImage(miningSiteIcon, 1, 1, null);
|
||||
|
||||
ROOFTOP_COURSE_ICON = new BufferedImage(iconBufferSize, iconBufferSize, BufferedImage.TYPE_INT_ARGB);
|
||||
final BufferedImage rooftopCourseIcon = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, "rooftop_course_icon.png");
|
||||
ROOFTOP_COURSE_ICON.getGraphics().drawImage(rooftopCourseIcon, 1, 1, null);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private WorldMapConfig config;
|
||||
|
||||
@Inject
|
||||
private WorldMapPointManager worldMapPointManager;
|
||||
|
||||
private int agilityLevel = 0;
|
||||
private int woodcuttingLevel = 0;
|
||||
|
||||
@Provides
|
||||
WorldMapConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(WorldMapConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
agilityLevel = client.getRealSkillLevel(Skill.AGILITY);
|
||||
woodcuttingLevel = client.getRealSkillLevel(Skill.WOODCUTTING);
|
||||
updateShownIcons();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
worldMapPointManager.removeIf(FairyRingPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(QuestStartPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(TeleportPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(TransportationPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(MinigamePoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(RareTreePoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(RunecraftingAltarPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(DungeonPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(FishingSpotPoint.class::isInstance);
|
||||
worldMapPointManager.removeIf(AgilityCoursePoint.class::isInstance);
|
||||
agilityLevel = 0;
|
||||
woodcuttingLevel = 0;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!event.getGroup().equals(CONFIG_KEY))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateShownIcons();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatChanged(StatChanged statChanged)
|
||||
{
|
||||
switch (statChanged.getSkill())
|
||||
{
|
||||
case AGILITY:
|
||||
{
|
||||
int newAgilityLevel = statChanged.getLevel();
|
||||
if (newAgilityLevel != agilityLevel)
|
||||
{
|
||||
agilityLevel = newAgilityLevel;
|
||||
updateAgilityIcons();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WOODCUTTING:
|
||||
{
|
||||
int newWoodcutLevel = statChanged.getLevel();
|
||||
if (newWoodcutLevel != woodcuttingLevel)
|
||||
{
|
||||
woodcuttingLevel = newWoodcutLevel;
|
||||
updateRareTreeIcons();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded widgetLoaded)
|
||||
{
|
||||
if (widgetLoaded.getGroupId() == WidgetID.WORLD_MAP_GROUP_ID)
|
||||
{
|
||||
// Quest icons are per-account due to showing quest status,
|
||||
// so we recreate them each time the map is loaded
|
||||
updateQuestStartPointIcons();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAgilityIcons()
|
||||
{
|
||||
worldMapPointManager.removeIf(AgilityShortcutPoint.class::isInstance);
|
||||
|
||||
if (config.agilityShortcutLevelIcon() || config.agilityShortcutTooltips())
|
||||
{
|
||||
Arrays.stream(AgilityShortcut.values())
|
||||
.filter(value -> value.getWorldMapLocation() != null)
|
||||
.map(value -> new AgilityShortcutPoint(value,
|
||||
agilityLevel > 0 && config.agilityShortcutLevelIcon() && value.getLevel() > agilityLevel ? NOPE_ICON : BLANK_ICON,
|
||||
config.agilityShortcutTooltips()))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAgilityCourseIcons()
|
||||
{
|
||||
worldMapPointManager.removeIf(AgilityCoursePoint.class::isInstance);
|
||||
|
||||
if (config.agilityCourseTooltip() || config.agilityCourseRooftop())
|
||||
{
|
||||
Arrays.stream(AgilityCourseLocation.values())
|
||||
.filter(value -> value.getLocation() != null)
|
||||
.map(value -> new AgilityCoursePoint(value,
|
||||
config.agilityCourseRooftop() && value.isRooftopCourse() ? ROOFTOP_COURSE_ICON : BLANK_ICON,
|
||||
config.agilityCourseTooltip()))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRareTreeIcons()
|
||||
{
|
||||
worldMapPointManager.removeIf(RareTreePoint.class::isInstance);
|
||||
|
||||
if (config.rareTreeLevelIcon() || config.rareTreeTooltips())
|
||||
{
|
||||
Arrays.stream(RareTreeLocation.values()).forEach(rareTree ->
|
||||
Arrays.stream(rareTree.getLocations())
|
||||
.map(point -> new RareTreePoint(point,
|
||||
rareTree.getTooltip(),
|
||||
woodcuttingLevel > 0 && config.rareTreeLevelIcon() &&
|
||||
rareTree.getLevelReq() > woodcuttingLevel ? NOPE_ICON : BLANK_ICON,
|
||||
config.rareTreeTooltips()))
|
||||
.forEach(worldMapPointManager::add));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShownIcons()
|
||||
{
|
||||
updateAgilityIcons();
|
||||
updateAgilityCourseIcons();
|
||||
updateRareTreeIcons();
|
||||
updateQuestStartPointIcons();
|
||||
|
||||
worldMapPointManager.removeIf(FairyRingPoint.class::isInstance);
|
||||
if (config.fairyRingIcon() || config.fairyRingTooltips())
|
||||
{
|
||||
Arrays.stream(FairyRingLocation.values())
|
||||
.map(value -> new FairyRingPoint(value,
|
||||
config.fairyRingIcon() ? FAIRY_TRAVEL_ICON : BLANK_ICON,
|
||||
config.fairyRingTooltips()))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(MinigamePoint.class::isInstance);
|
||||
if (config.minigameTooltip())
|
||||
{
|
||||
Arrays.stream(MinigameLocation.values())
|
||||
.map(value -> new MinigamePoint(value, BLANK_ICON))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(TransportationPoint.class::isInstance);
|
||||
if (config.transportationTeleportTooltips())
|
||||
{
|
||||
Arrays.stream(TransportationPointLocation.values())
|
||||
.map(value -> new TransportationPoint(value, BLANK_ICON))
|
||||
.forEach((worldMapPointManager::add));
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(FarmingPatchPoint.class::isInstance);
|
||||
if (config.farmingPatchTooltips())
|
||||
{
|
||||
Arrays.stream(FarmingPatchLocation.values()).forEach(location ->
|
||||
Arrays.stream(location.getLocations())
|
||||
.map(point -> new FarmingPatchPoint(point, location.getTooltip(), BLANK_ICON))
|
||||
.forEach(worldMapPointManager::add)
|
||||
);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(TeleportPoint.class::isInstance);
|
||||
Arrays.stream(TeleportLocationData.values())
|
||||
.filter(data ->
|
||||
{
|
||||
switch (data.getType())
|
||||
{
|
||||
case NORMAL_MAGIC:
|
||||
return config.normalTeleportIcon();
|
||||
case ANCIENT_MAGICKS:
|
||||
return config.ancientTeleportIcon();
|
||||
case LUNAR_MAGIC:
|
||||
return config.lunarTeleportIcon();
|
||||
case ARCEUUS_MAGIC:
|
||||
return config.arceuusTeleportIcon();
|
||||
case JEWELLERY:
|
||||
return config.jewelleryTeleportIcon();
|
||||
case SCROLL:
|
||||
return config.scrollTeleportIcon();
|
||||
case OTHER:
|
||||
return config.miscellaneousTeleportIcon();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}).map(TeleportPoint::new)
|
||||
.forEach(worldMapPointManager::add);
|
||||
|
||||
worldMapPointManager.removeIf(RunecraftingAltarPoint.class::isInstance);
|
||||
if (config.runecraftingAltarIcon())
|
||||
{
|
||||
Arrays.stream(RunecraftingAltarLocation.values())
|
||||
.map(RunecraftingAltarPoint::new)
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(MiningSitePoint.class::isInstance);
|
||||
if (config.miningSiteTooltips())
|
||||
{
|
||||
Arrays.stream(MiningSiteLocation.values())
|
||||
.map(value -> new MiningSitePoint(value, value.isIconRequired() ? MINING_SITE_ICON : BLANK_ICON))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(DungeonPoint.class::isInstance);
|
||||
if (config.dungeonTooltips())
|
||||
{
|
||||
Arrays.stream(DungeonLocation.values())
|
||||
.map(value -> new DungeonPoint(value, BLANK_ICON))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(HunterAreaPoint.class::isInstance);
|
||||
if (config.hunterAreaTooltips())
|
||||
{
|
||||
Arrays.stream(HunterAreaLocation.values())
|
||||
.map(value -> new HunterAreaPoint(value, BLANK_ICON))
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(FishingSpotPoint.class::isInstance);
|
||||
if (config.fishingSpotTooltips())
|
||||
{
|
||||
Arrays.stream(FishingSpotLocation.values()).forEach(location ->
|
||||
Arrays.stream(location.getLocations())
|
||||
.map(point -> new FishingSpotPoint(point, location.getTooltip(), BLANK_ICON))
|
||||
.forEach(worldMapPointManager::add)
|
||||
);
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(KourendTaskPoint.class::isInstance);
|
||||
if (config.kourendTaskTooltips())
|
||||
{
|
||||
Arrays.stream(KourendTaskLocation.values())
|
||||
.map(KourendTaskPoint::new)
|
||||
.forEach(worldMapPointManager::add);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateQuestStartPointIcons()
|
||||
{
|
||||
worldMapPointManager.removeIf(QuestStartPoint.class::isInstance);
|
||||
|
||||
if (!config.questStartTooltips())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Must setup the quest icons on the client thread, after the player has logged in.
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Arrays.stream(QuestStartLocation.values())
|
||||
.map(this::createQuestStartPoint)
|
||||
.forEach(worldMapPointManager::add);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private QuestStartPoint createQuestStartPoint(QuestStartLocation data)
|
||||
{
|
||||
Quest[] quests = data.getQuests();
|
||||
|
||||
// Get first uncompleted quest. Else, return the last quest.
|
||||
Quest quest = null;
|
||||
for (Quest q : quests)
|
||||
{
|
||||
if (q.getState(client) != QuestState.FINISHED)
|
||||
{
|
||||
quest = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (quest == null)
|
||||
{
|
||||
quest = quests[quests.length - 1];
|
||||
}
|
||||
|
||||
BufferedImage icon = BLANK_ICON;
|
||||
String tooltip = "";
|
||||
if (quest != null)
|
||||
{
|
||||
tooltip = quest.getName();
|
||||
switch (quest.getState(client))
|
||||
{
|
||||
case FINISHED:
|
||||
icon = FINISHED_ICON;
|
||||
tooltip += " - Finished";
|
||||
break;
|
||||
case IN_PROGRESS:
|
||||
icon = STARTED_ICON;
|
||||
tooltip += " - Started";
|
||||
break;
|
||||
case NOT_STARTED:
|
||||
icon = NOT_STARTED_ICON;
|
||||
tooltip += " - Not Started";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new QuestStartPoint(data.getLocation(), icon, tooltip);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Hexagon <hexagon@fking.work>
|
||||
* 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.zalcano;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicsObject;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
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.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
class ZalcanoOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final ZalcanoPlugin zalcanoPlugin;
|
||||
|
||||
@Inject
|
||||
private ZalcanoOverlay(Client client, ZalcanoPlugin zalcanoPlugin)
|
||||
{
|
||||
this.client = client;
|
||||
this.zalcanoPlugin = zalcanoPlugin;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
setPriority(OverlayPriority.MED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
List<GraphicsObject> rocks = zalcanoPlugin.getRocks();
|
||||
if (!rocks.isEmpty())
|
||||
{
|
||||
rocks.removeIf(GraphicsObject::finished);
|
||||
|
||||
for (GraphicsObject graphicsObject : rocks)
|
||||
{
|
||||
final Player localPlayer = client.getLocalPlayer();
|
||||
final LocalPoint graphicsObjectLocation = graphicsObject.getLocation();
|
||||
final Polygon polygon = Perspective.getCanvasTilePoly(client, graphicsObjectLocation);
|
||||
|
||||
if (polygon != null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, polygon, localPlayer.getLocalLocation().equals(graphicsObjectLocation) ? Color.RED : Color.ORANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalPoint targetedGlowingRock = zalcanoPlugin.getTargetedGlowingRock();
|
||||
if (targetedGlowingRock != null && client.getGameCycle() < zalcanoPlugin.getTargetedGlowingRockEndCycle())
|
||||
{
|
||||
final Polygon polygon = Perspective.getCanvasTileAreaPoly(client, targetedGlowingRock, 3);
|
||||
|
||||
if (polygon != null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, polygon, Color.RED);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2020, dekvall <https://github.com/dekvall>
|
||||
* 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 HOLDER 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.zalcano;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.client.ui.overlay.OverlayPanel;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
|
||||
class ZalcanoPanel extends OverlayPanel
|
||||
{
|
||||
private final ZalcanoPlugin plugin;
|
||||
|
||||
@Inject
|
||||
public ZalcanoPanel(ZalcanoPlugin plugin)
|
||||
{
|
||||
super(plugin);
|
||||
setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D g)
|
||||
{
|
||||
if (!plugin.isInCavern())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Health damage:")
|
||||
.leftColor(colorFromCount(plugin.getHealthDamage()))
|
||||
.right(Integer.toString(plugin.getHealthDamage()))
|
||||
.build());
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Shield damage:")
|
||||
.leftColor(colorFromCount(plugin.getShieldDamage()))
|
||||
.right(Integer.toString(plugin.getShieldDamage()))
|
||||
.build());
|
||||
|
||||
return super.render(g);
|
||||
}
|
||||
|
||||
private static Color colorFromCount(int damage)
|
||||
{
|
||||
if (damage >= 50)
|
||||
{
|
||||
// Eligible for uniques/pet
|
||||
return Color.GREEN;
|
||||
}
|
||||
if (damage >= 30)
|
||||
{
|
||||
// Eligible for drops
|
||||
return Color.YELLOW;
|
||||
}
|
||||
return Color.RED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Hexagon <hexagon@fking.work>
|
||||
* 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.zalcano;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import static net.runelite.api.GraphicID.GRAPHICS_OBJECT_ROCKFALL;
|
||||
import net.runelite.api.GraphicsObject;
|
||||
import net.runelite.api.Hitsplat;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import static net.runelite.api.NpcID.ZALCANO;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Projectile;
|
||||
import static net.runelite.api.ProjectileID.ZALCANO_PROJECTILE_FIREBALL;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GraphicsObjectCreated;
|
||||
import net.runelite.api.events.HitsplatApplied;
|
||||
import net.runelite.api.events.NpcChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Zalcano",
|
||||
description = "Assistance for the Zalcano fight",
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class ZalcanoPlugin extends Plugin
|
||||
{
|
||||
private static final int ZALCANO_WEAKENED = NpcID.ZALCANO_9050;
|
||||
private static final int GOLEM = NpcID.GOLEM_9051;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private ZalcanoOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private ZalcanoPanel panel;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Getter
|
||||
private LocalPoint targetedGlowingRock;
|
||||
@Getter
|
||||
private int targetedGlowingRockEndCycle;
|
||||
private WorldPoint lastGlowingRock;
|
||||
|
||||
@Getter
|
||||
private final List<GraphicsObject> rocks = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
private int healthDamage;
|
||||
@Getter
|
||||
private int shieldDamage;
|
||||
@Getter
|
||||
private boolean inCavern;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(panel);
|
||||
rocks.clear();
|
||||
|
||||
resetDamageCounter();
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
inCavern = isHealthbarActive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(panel);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGraphicsObjectCreated(GraphicsObjectCreated graphicsObjectCreated)
|
||||
{
|
||||
GraphicsObject graphicsObject = graphicsObjectCreated.getGraphicsObject();
|
||||
if (graphicsObject.getId() == GRAPHICS_OBJECT_ROCKFALL)
|
||||
{
|
||||
rocks.add(graphicsObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
GameState gameState = event.getGameState();
|
||||
if (gameState == GameState.LOADING)
|
||||
{
|
||||
rocks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
boolean wasInCavern = inCavern;
|
||||
inCavern = isHealthbarActive();
|
||||
|
||||
if (!inCavern && wasInCavern)
|
||||
{
|
||||
resetDamageCounter();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
final NPC npc = event.getNpc();
|
||||
|
||||
if (npc.getId() == GOLEM)
|
||||
{
|
||||
client.setHintArrow(npc);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
{
|
||||
final NPC npc = event.getNpc();
|
||||
|
||||
if (npc.getId() == ZALCANO_WEAKENED)
|
||||
{
|
||||
client.clearHintArrow();
|
||||
}
|
||||
else if (npc.getId() == GOLEM)
|
||||
{
|
||||
if (lastGlowingRock != null)
|
||||
{
|
||||
client.setHintArrow(lastGlowingRock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetDamageCounter()
|
||||
{
|
||||
healthDamage = 0;
|
||||
shieldDamage = 0;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||
{
|
||||
final GameObject gameObject = event.getGameObject();
|
||||
|
||||
if (gameObject.getId() == ObjectID.ROCK_FORMATION_GLOWING)
|
||||
{
|
||||
WorldPoint worldLocation = lastGlowingRock = gameObject.getWorldLocation();
|
||||
client.setHintArrow(worldLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcChanged(NpcChanged event)
|
||||
{
|
||||
final NPC npc = event.getNpc();
|
||||
|
||||
if (npc.getId() == ZALCANO_WEAKENED)
|
||||
{
|
||||
client.setHintArrow(npc);
|
||||
}
|
||||
else if (npc.getId() == ZALCANO)
|
||||
{
|
||||
if (lastGlowingRock != null)
|
||||
{
|
||||
client.setHintArrow(lastGlowingRock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onProjectileMoved(ProjectileMoved event)
|
||||
{
|
||||
final Projectile projectile = event.getProjectile();
|
||||
|
||||
if (projectile.getId() == ZALCANO_PROJECTILE_FIREBALL)
|
||||
{
|
||||
targetedGlowingRock = event.getPosition();
|
||||
targetedGlowingRockEndCycle = projectile.getEndCycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onHitsplatApplied(HitsplatApplied event)
|
||||
{
|
||||
final Actor actor = event.getActor();
|
||||
|
||||
if (!(actor instanceof NPC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int npcId = ((NPC) actor).getId();
|
||||
if (!(npcId == ZALCANO_WEAKENED || npcId == ZALCANO))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Hitsplat hitsplat = event.getHitsplat();
|
||||
int damage = hitsplat.getAmount();
|
||||
|
||||
switch (hitsplat.getHitsplatType())
|
||||
{
|
||||
case DAMAGE_ME:
|
||||
healthDamage += damage;
|
||||
break;
|
||||
case DAMAGE_ME_ORANGE:
|
||||
shieldDamage += damage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHealthbarActive()
|
||||
{
|
||||
return client.getVar(VarPlayer.ZALCANO_FORM) != -1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user