Merge remote-tracking branch 'runelite/master'

This commit is contained in:
Owain van Brakel
2019-06-05 19:51:04 +02:00
47 changed files with 2331 additions and 2658 deletions

View File

@@ -69,7 +69,7 @@ public class CacheUploader implements Runnable
archive.setHash(hash);
String path = new StringBuilder()
.append(hashStr.substring(0, 2))
.append(hashStr, 0, 2)
.append('/')
.append(hashStr.substring(2))
.toString();

View File

@@ -116,7 +116,7 @@ public class FlatStorage implements Storage
{
int lidx = line.indexOf('=');
String key = line.substring(0, lidx);
String value = line.substring(lidx + 1, line.length());
String value = line.substring(lidx + 1);
if ("file".equals(key))
{
@@ -128,7 +128,7 @@ public class FlatStorage implements Storage
int vidx = value.indexOf('=');
FileData fd = new FileData();
fd.setId(Integer.parseInt(value.substring(0, vidx)));
fd.setNameHash(Integer.parseInt(value.substring(vidx + 1, value.length())));
fd.setNameHash(Integer.parseInt(value.substring(vidx + 1)));
fileData.add(fd);
continue;
}

View File

@@ -104,7 +104,7 @@ public class CacheService
{
String hashStr = BaseEncoding.base16().encode(archiveEntry.getHash());
String path = new StringBuilder()
.append(hashStr.substring(0, 2))
.append(hashStr, 0, 2)
.append('/')
.append(hashStr.substring(2))
.toString();

View File

@@ -151,6 +151,13 @@ public interface Client extends GameEngine
*/
void setPassword(String password);
/**
* Sets the 6 digit pin used for authenticator on login screen.
*
* @param otp one time password
*/
void setOtp(String otp);
/**
* Gets currently selected login field. 0 is username, and 1 is password.
*
@@ -158,6 +165,13 @@ public interface Client extends GameEngine
*/
int getCurrentLoginField();
/**
* Gets index of current login state. 2 is username/password form, 4 is authenticator form
*
* @return current login state index
*/
int getLoginIndex();
/**
* Gets the account type of the logged in player.
*
@@ -1352,6 +1366,13 @@ public interface Client extends GameEngine
*/
boolean isInInstancedRegion();
/**
* Get the number of client ticks an item has been pressed
*
* @return the number of client ticks an item has been pressed
*/
int getItemPressedDuration();
/**
* Sets whether the client is hiding entities.
* <p>
@@ -1598,6 +1619,19 @@ public interface Client extends GameEngine
void checkClickbox(Model model, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash);
/**
* Get the if1 widget whose item is being dragged
*
* @return
*/
Widget getIf1DraggedWidget();
/**
* Get the item index of the item being dragged on an if1 widget
* @return
*/
int getIf1DraggedItemIndex();
/**
* Sets if a widget is in target mode
*/

View File

@@ -41,6 +41,10 @@ public enum GameState
* The client is at the login screen.
*/
LOGIN_SCREEN(10),
/**
* The client is at the login screen entering authenticator code.
*/
LOGIN_SCREEN_AUTHENTICATOR(11),
/**
* There is a player logging in.
*/

View File

@@ -27,6 +27,7 @@ package net.runelite.api;
public class GraphicID
{
public static final int WINE_MAKE = 47;
public static final int SPLASH = 85;
public static final int GREY_BUBBLE_TELEPORT = 86;
public static final int TELEPORT = 111;

View File

@@ -79,6 +79,10 @@ public class ArdougneDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.FAIRYTALE_II__CURE_A_QUEEN, true));
// HARD
// When the task is completed "the Totem" changes to "Totem" - so we add
// both variations.
add("Recharge some Jewellery at the Totem in the Legends Guild.",
new QuestRequirement(Quest.LEGENDS_QUEST));
add("Recharge some Jewellery at Totem in the Legends Guild.",
new QuestRequirement(Quest.LEGENDS_QUEST));
add("Enter the Magic Guild.",

View File

@@ -46,7 +46,7 @@ class Obstacles
// Draynor
ROUGH_WALL, TIGHTROPE, TIGHTROPE_11406, NARROW_WALL, WALL_11630, GAP_11631, CRATE_11632, STILE_7527,
// Al-Kharid
ROUGH_WALL_11633, TIGHTROPE_14398, CABLE, ZIP_LINE, TROPICAL_TREE_14404, ROOF_TOP_BEAMS,
ROUGH_WALL_11633, TIGHTROPE_14398, CABLE, ZIP_LINE_14403, TROPICAL_TREE_14404, ROOF_TOP_BEAMS,
TIGHTROPE_14409, GAP_14399,
// Pyramid
STAIRS_10857, LOW_WALL_10865, LEDGE_10860, PLANK_10868, GAP_10882, LEDGE_10886, STAIRS_10857, GAP_10884,

View File

@@ -328,7 +328,10 @@ public class BarbarianAssaultPlugin extends Plugin
{
overlay.setCurrentRound(null);
if (config.waveTimes() && gameTime != null)
// Use an instance check to determine if this is exiting a game or a tutorial
// After exiting tutorials there is a small delay before changing IN_GAME_BA back to
// 0 whereas when in a real wave it changes while still in the instance.
if (config.waveTimes() && gameTime != null && client.isInInstancedRegion())
{
announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true));
}

View File

@@ -33,8 +33,8 @@ import javax.annotation.Nonnull;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.EquipmentInventorySlot;
import static net.runelite.api.EquipmentInventorySlot.LEGS;
import static net.runelite.api.EquipmentInventorySlot.*;
import static net.runelite.api.EquipmentInventorySlot.LEGS;
import net.runelite.api.Item;
import net.runelite.api.ItemID;
import static net.runelite.api.ItemID.*;
@@ -47,13 +47,13 @@ import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
import net.runelite.client.plugins.cluescrolls.clues.emote.AllRequirementsCollection;
import net.runelite.client.plugins.cluescrolls.clues.emote.AnyRequirementCollection;
import net.runelite.client.plugins.cluescrolls.clues.emote.Emote;
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER;
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.*;
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER;
import net.runelite.client.plugins.cluescrolls.clues.emote.ItemRequirement;
import net.runelite.client.plugins.cluescrolls.clues.emote.RangeItemRequirement;
import net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit;
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS;
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.*;
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS;
import net.runelite.client.plugins.cluescrolls.clues.emote.SingleItemRequirement;
import net.runelite.client.plugins.cluescrolls.clues.emote.SlotLimitationRequirement;
import net.runelite.client.ui.overlay.OverlayUtil;
@@ -97,7 +97,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
new EmoteClue("Cheer in the Ogre Pen in the Training Camp. Show you are angry before you talk to me. Equip a green dragonhide body and chaps and a steel square shield.", OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP, new WorldPoint(2527, 3375, 0), CHEER, ANGRY, item(GREEN_DHIDE_BODY), item(GREEN_DHIDE_CHAPS), item(STEEL_SQ_SHIELD)),
new EmoteClue("Cheer in the Entrana church. Beware of double agents! Equip a full set of black dragonhide armour.", ENTRANA_CHAPEL, new WorldPoint(2852, 3349, 0), CHEER, item(BLACK_DHIDE_VAMB), item(BLACK_DHIDE_CHAPS), item(BLACK_DHIDE_BODY)),
new EmoteClue("Cheer for the monks at Port Sarim. Equip a coif, steel plateskirt and a sapphire necklace.", NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM, new WorldPoint(3047, 3237, 0), CHEER, item(COIF), item(STEEL_PLATESKIRT), item(SAPPHIRE_NECKLACE)),
new EmoteClue("Clap in the main exam room in the Exam Centre. Equip a white apron, green gnome boots and leather gloves.", INSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3361, 3339, 0), CLAP, item(WHITE_APRON), item(GREEN_BOOTS), item(LEATHER_GLOVES)),
new EmoteClue("Clap in the main exam room in the Exam Centre. Equip a white apron, green gnome boots and leather gloves.", OUTSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3361, 3339, 0), CLAP, item(WHITE_APRON), item(GREEN_BOOTS), item(LEATHER_GLOVES)),
new EmoteClue("Clap on the causeway to the Wizards' Tower. Equip an iron medium helmet, emerald ring and a white apron.", ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER, new WorldPoint(3113, 3196, 0), CLAP, item(IRON_MED_HELM), item(EMERALD_RING), item(WHITE_APRON)),
new EmoteClue("Clap on the top level of the mill, north of East Ardougne. Equip a blue gnome robe top, HAM robe bottom and an unenchanted tiara.", UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL, new WorldPoint(2635, 3385, 3), CLAP, item(BLUE_ROBE_TOP), item(HAM_ROBE), item(TIARA)),
new EmoteClue("Clap in Seers court house. Spin before you talk to me. Equip an adamant halberd, blue mystic robe bottom and a diamond ring.", OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE, new WorldPoint(2735, 3469, 0), CLAP, SPIN, item(ADAMANT_HALBERD), item(MYSTIC_ROBE_BOTTOM), item(DIAMOND_RING)),
@@ -118,7 +118,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
new EmoteClue("Dance at the entrance to the Grand Exchange. Equip a pink skirt, pink robe top and a body tiara.", SOUTH_OF_THE_GRAND_EXCHANGE, new WorldPoint(3165, 3467, 0), DANCE, item(PINK_SKIRT), item(PINK_ROBE_TOP), item(BODY_TIARA)),
new EmoteClue("Goblin Salute in the Goblin Village. Beware of double agents! Equip a bandos godsword, a bandos cloak and a bandos platebody.", OUTSIDE_MUDKNUCKLES_HUT, new WorldPoint(2956, 3505, 0), GOBLIN_SALUTE, item(BANDOS_PLATEBODY), item(BANDOS_CLOAK), item(BANDOS_GODSWORD)),
new EmoteClue("Headbang in the mine north of Al Kharid. Equip a desert shirt, leather gloves and leather boots.", AL_KHARID_SCORPION_MINE, new WorldPoint(3299, 3289, 0), HEADBANG, item(DESERT_SHIRT), item(LEATHER_GLOVES), item(LEATHER_BOOTS)),
new EmoteClue("Headbang at the exam center. Beware of double agents! Equip a mystic fire staff, a diamond bracelet and rune boots.", OUTSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3362, 3340, 0), HEADBANG, item(MYSTIC_FIRE_STAFF), item(DIAMOND_BRACELET), item(RUNE_BOOTS)),
new EmoteClue("Headbang at the exam center. Beware of double agents! Equip a mystic fire staff, a diamond bracelet and rune boots.", INSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3362, 3340, 0), HEADBANG, item(MYSTIC_FIRE_STAFF), item(DIAMOND_BRACELET), item(RUNE_BOOTS)),
new EmoteClue("Headbang at the top of Slayer Tower. Equip a seercull, a combat bracelet and helm of Neitiznot.", OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM, new WorldPoint(3421, 3537, 2), HEADBANG, item(SEERCULL), range("Combat bracelet", COMBAT_BRACELET4, COMBAT_BRACELET), item(HELM_OF_NEITIZNOT)),
new EmoteClue("Dance a jig by the entrance to the Fishing Guild. Equip an emerald ring, a sapphire amulet, and a bronze chain body.", OUTSIDE_THE_FISHING_GUILD, new WorldPoint(2610, 3391, 0), JIG, item(EMERALD_RING), item(SAPPHIRE_AMULET), item(BRONZE_CHAINBODY)),
new EmoteClue("Dance a jig under Shantay's Awning. Bow before you talk to me. Equip a pointed blue snail helmet, an air staff and a bronze square shield.", SHANTAY_PASS, new WorldPoint(3304, 3124, 0), JIG, BOW, any("Bruise blue snelm (pointed)", item(BRUISE_BLUE_SNELM_3343)), item(STAFF_OF_AIR), item(BRONZE_SQ_SHIELD)),

View File

@@ -51,127 +51,127 @@ import static net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdArea.
@Getter
public enum HotColdLocation
{
ASGARNIA_WARRIORS(new WorldPoint(2860, 3562, 0), ASGARNIA, "North of the Warriors' Guild in Burthorpe."),
ASGARNIA_JATIX(new WorldPoint(2914, 3429, 0), ASGARNIA, "East of Jatix's Herblore Shop in Taverley."),
ASGARNIA_BARB(new WorldPoint(3036, 3439, 0), ASGARNIA, "West of Barbarian Village."),
ASGARNIA_MIAZRQA(new WorldPoint(2973, 3489, 0), ASGARNIA, "North of Miazrqa's tower, outside Goblin Village."),
ASGARNIA_COW(new WorldPoint(3033, 3308, 0), ASGARNIA, "In the cow pen north of Sarah's Farming Shop."),
ASGARNIA_PARTY_ROOM(new WorldPoint(3026, 3363, 0), ASGARNIA, "Outside the Falador Party Room."),
ASGARNIA_CRAFT_GUILD(new WorldPoint(2917, 3295, 0), ASGARNIA, "Outside the Crafting Guild cow pen."),
ASGARNIA_RIMMINGTON(new WorldPoint(2978, 3241, 0), ASGARNIA, "In the centre of the Rimmington mine."),
ASGARNIA_WARRIORS(new WorldPoint(2860, 3562, 0), ASGARNIA, "North of the Warriors' Guild in Burthorpe."),
ASGARNIA_JATIX(new WorldPoint(2914, 3429, 0), ASGARNIA, "East of Jatix's Herblore Shop in Taverley."),
ASGARNIA_BARB(new WorldPoint(3036, 3439, 0), ASGARNIA, "West of Barbarian Village."),
ASGARNIA_MIAZRQA(new WorldPoint(2973, 3489, 0), ASGARNIA, "North of Miazrqa's tower, outside Goblin Village."),
ASGARNIA_COW(new WorldPoint(3033, 3308, 0), ASGARNIA, "In the cow pen north of Sarah's Farming Shop."),
ASGARNIA_PARTY_ROOM(new WorldPoint(3026, 3363, 0), ASGARNIA, "Outside the Falador Party Room."),
ASGARNIA_CRAFT_GUILD(new WorldPoint(2917, 3295, 0), ASGARNIA, "Outside the Crafting Guild cow pen."),
ASGARNIA_RIMMINGTON(new WorldPoint(2978, 3241, 0), ASGARNIA, "In the centre of the Rimmington mine."),
ASGARNIA_MUDSKIPPER(new WorldPoint(2984, 3109, 0), ASGARNIA, "Mudskipper Point, on the starfish in the south-west corner."),
ASGARNIA_TROLL(new WorldPoint(2910, 3616, 0), ASGARNIA, "The Troll arena, where the player fights Dad during the Troll Stronghold quest. Bring climbing boots if travelling from Burthorpe."),
DESERT_GENIE(new WorldPoint(3364, 2910, 0), DESERT, "West of Nardah genie cave."),
DESERT_ALKHARID_MINE(new WorldPoint(3282, 3270, 0), DESERT, "West of Al Kharid mine."),
DESERT_MENAPHOS_GATE(new WorldPoint(3224, 2816, 0), DESERT, "North of Menaphos gate."),
ASGARNIA_TROLL(new WorldPoint(2910, 3616, 0), ASGARNIA, "The Troll arena, where the player fights Dad during the Troll Stronghold quest. Bring climbing boots if travelling from Burthorpe."),
DESERT_GENIE(new WorldPoint(3364, 2910, 0), DESERT, "West of Nardah genie cave."),
DESERT_ALKHARID_MINE(new WorldPoint(3282, 3270, 0), DESERT, "West of Al Kharid mine."),
DESERT_MENAPHOS_GATE(new WorldPoint(3224, 2816, 0), DESERT, "North of Menaphos gate."),
DESERT_BEDABIN_CAMP(new WorldPoint(3164, 3050, 0), DESERT, "Bedabin Camp, dig around the north tent."),
DESERT_UZER(new WorldPoint(3431, 3106, 0), DESERT, "West of Uzer."),
DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach."),
DESERT_MTA(new WorldPoint(3350, 3293, 0), DESERT, "Next to Mage Training Arena."),
DESERT_SHANTY(new WorldPoint(3294, 3106, 0), DESERT, "South-west of Shantay Pass."),
FELDIP_HILLS_JIGGIG(new WorldPoint(2413, 3055, 0), FELDIP_HILLS, "West of Jiggig, east of the fairy ring bkp."),
FELDIP_HILLS_SW(new WorldPoint(2582, 2895, 0), FELDIP_HILLS, "West of the southeasternmost lake in Feldip Hills."),
FELDIP_HILLS_GNOME_GLITER(new WorldPoint(2553, 2972, 0), FELDIP_HILLS, "East of the gnome glider (Lemantolly Undri)."),
FELDIP_HILLS_RANTZ(new WorldPoint(2611, 2946, 0), FELDIP_HILLS, "South of Rantz, six steps west of the empty glass bottles."),
FELDIP_HILLS_SOUTH(new WorldPoint(2487, 3005, 0), FELDIP_HILLS, "South of Jiggig."),
FELDIP_HILLS_RED_CHIN(new WorldPoint(2532, 2900, 0), FELDIP_HILLS, "Outside the red chinchompa hunting ground entrance, south of the Hunting expert's hut."),
FELDIP_HILLS_SE(new WorldPoint(2567, 2916, 0), FELDIP_HILLS, "South-east of the ∩-shaped lake, near the icon."),
FELDIP_HILLS_CW_BALLOON(new WorldPoint(2452, 3108, 0), FELDIP_HILLS, "Directly west of the Castle Wars balloon."),
FREMENNIK_PROVINCE_MTN_CAMP(new WorldPoint(2804, 3672, 0), FREMENNIK_PROVINCE, "At the Mountain Camp."),
FREMENNIK_PROVINCE_RELLEKKA_HUNTER(new WorldPoint(2724, 3783, 0), FREMENNIK_PROVINCE, "At the Rellekka Hunter area, near the icon."),
FREMENNIK_PROVINCE_KELGADRIM_ENTRANCE(new WorldPoint(2715, 3689, 0), FREMENNIK_PROVINCE, "West of the Keldagrim entrance mine."),
FREMENNIK_PROVINCE_SW(new WorldPoint(2605, 3648, 0), FREMENNIK_PROVINCE, "Outside the fence in the south-western corner of Rellekka."),
FREMENNIK_PROVINCE_LIGHTHOUSE(new WorldPoint(2589, 3598, 0), FREMENNIK_PROVINCE, "South-east of the Lighthouse."),
FREMENNIK_PROVINCE_ETCETERIA_CASTLE(new WorldPoint(2614, 3867, 0), FREMENNIK_PROVINCE, "Inside Etceteria's castle, in the southern staircase."),
FREMENNIK_PROVINCE_MISC_COURTYARD(new WorldPoint(2529, 3867, 0), FREMENNIK_PROVINCE, "Outside Miscellania's courtyard."),
DESERT_UZER(new WorldPoint(3431, 3106, 0), DESERT, "West of Uzer."),
DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach."),
DESERT_MTA(new WorldPoint(3350, 3293, 0), DESERT, "Next to Mage Training Arena."),
DESERT_SHANTY(new WorldPoint(3294, 3106, 0), DESERT, "South-west of Shantay Pass."),
FELDIP_HILLS_JIGGIG(new WorldPoint(2413, 3055, 0), FELDIP_HILLS, "West of Jiggig, east of the fairy ring bkp."),
FELDIP_HILLS_SW(new WorldPoint(2582, 2895, 0), FELDIP_HILLS, "West of the southeasternmost lake in Feldip Hills."),
FELDIP_HILLS_GNOME_GLITER(new WorldPoint(2553, 2972, 0), FELDIP_HILLS, "East of the gnome glider (Lemantolly Undri)."),
FELDIP_HILLS_RANTZ(new WorldPoint(2611, 2946, 0), FELDIP_HILLS, "South of Rantz, six steps west of the empty glass bottles."),
FELDIP_HILLS_SOUTH(new WorldPoint(2487, 3005, 0), FELDIP_HILLS, "South of Jiggig."),
FELDIP_HILLS_RED_CHIN(new WorldPoint(2532, 2900, 0), FELDIP_HILLS, "Outside the red chinchompa hunting ground entrance, south of the Hunting expert's hut."),
FELDIP_HILLS_SE(new WorldPoint(2567, 2916, 0), FELDIP_HILLS, "South-east of the ∩-shaped lake, near the icon."),
FELDIP_HILLS_CW_BALLOON(new WorldPoint(2452, 3108, 0), FELDIP_HILLS, "Directly west of the Castle Wars balloon."),
FREMENNIK_PROVINCE_MTN_CAMP(new WorldPoint(2804, 3672, 0), FREMENNIK_PROVINCE, "At the Mountain Camp."),
FREMENNIK_PROVINCE_RELLEKKA_HUNTER(new WorldPoint(2724, 3783, 0), FREMENNIK_PROVINCE, "At the Rellekka Hunter area, near the icon."),
FREMENNIK_PROVINCE_KELGADRIM_ENTRANCE(new WorldPoint(2715, 3689, 0), FREMENNIK_PROVINCE, "West of the Keldagrim entrance mine."),
FREMENNIK_PROVINCE_SW(new WorldPoint(2605, 3648, 0), FREMENNIK_PROVINCE, "Outside the fence in the south-western corner of Rellekka."),
FREMENNIK_PROVINCE_LIGHTHOUSE(new WorldPoint(2589, 3598, 0), FREMENNIK_PROVINCE, "South-east of the Lighthouse."),
FREMENNIK_PROVINCE_ETCETERIA_CASTLE(new WorldPoint(2614, 3867, 0), FREMENNIK_PROVINCE, "Inside Etceteria's castle, in the southern staircase."),
FREMENNIK_PROVINCE_MISC_COURTYARD(new WorldPoint(2529, 3867, 0), FREMENNIK_PROVINCE, "Outside Miscellania's courtyard."),
FREMENNIK_PROVINCE_FREMMY_ISLES_MINE(new WorldPoint(2378, 3849, 0), FREMENNIK_PROVINCE, "Central Fremennik Isles mine."),
FREMENNIK_PROVINCE_WEST_ISLES_MINE(new WorldPoint(2313, 3854, 0), FREMENNIK_PROVINCE, "West Fremennik Isles mine."),
FREMENNIK_PROVINCE_WEST_JATIZSO_ENTRANCE(new WorldPoint(2391, 3813, 0), FREMENNIK_PROVINCE, "West of the Jatizso mine entrance."),
FREMENNIK_PROVINCE_WEST_JATIZSO_ENTRANCE(new WorldPoint(2391, 3813, 0), FREMENNIK_PROVINCE, "West of the Jatizso mine entrance."),
FREMENNIK_PROVINCE_PIRATES_COVE(new WorldPoint(2210, 3814, 0), FREMENNIK_PROVINCE, "Pirates' Cove"),
FREMENNIK_PROVINCE_ASTRAL_ALTER(new WorldPoint(2147, 3862, 0), FREMENNIK_PROVINCE, "Astral altar"),
FREMENNIK_PROVINCE_LUNAR_VILLAGE(new WorldPoint(2087, 3915, 0), FREMENNIK_PROVINCE, "Lunar Isle, inside the village."),
FREMENNIK_PROVINCE_LUNAR_NORTH(new WorldPoint(2106, 3949, 0), FREMENNIK_PROVINCE, "Lunar Isle, north of the village."),
KANDARIN_SINCLAR_MANSION(new WorldPoint(2726, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut."),
KANDARIN_SINCLAR_MANSION(new WorldPoint(2726, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut."),
KANDARIN_CATHERBY(new WorldPoint(2774, 3433, 0), KANDARIN, "Catherby, between the bank and the beehives, near small rock formation."),
KANDARIN_GRAND_TREE(new WorldPoint(2444, 3503, 0), KANDARIN, "Grand Tree, just east of the terrorchick gnome enclosure."),
KANDARIN_SEERS(new WorldPoint(2735, 3486, 0), KANDARIN, "Between the Seers' Village bank and Camelot."),
KANDARIN_SEERS(new WorldPoint(2735, 3486, 0), KANDARIN, "Between the Seers' Village bank and Camelot."),
KANDARIN_MCGRUBORS_WOOD(new WorldPoint(2653, 3485, 0), KANDARIN, "McGrubor's Wood"),
KANDARIN_FISHING_BUILD(new WorldPoint(2586, 3372, 0), KANDARIN, "South of Fishing Guild"),
KANDARIN_WITCHHAVEN(new WorldPoint(2708, 3304, 0), KANDARIN, "Outside Witchaven, west of Jeb, Holgart, and Caroline."),
KANDARIN_NECRO_TOWER(new WorldPoint(2669, 3242, 0), KANDARIN, "Ground floor inside the Necromancer Tower. Easily accessed by using fairy ring code djp."),
KANDARIN_FIGHT_ARENA(new WorldPoint(2587, 3134, 0), KANDARIN, "South of the Fight Arena, north-west of the Nightmare Zone."),
KANDARIN_TREE_GNOME_VILLAGE(new WorldPoint(2526, 3160, 0), KANDARIN, "Tree Gnome Village, near the general store icon."),
KANDARIN_FISHING_BUILD(new WorldPoint(2586, 3372, 0), KANDARIN, "South of Fishing Guild"),
KANDARIN_WITCHHAVEN(new WorldPoint(2708, 3304, 0), KANDARIN, "Outside Witchaven, west of Jeb, Holgart, and Caroline."),
KANDARIN_NECRO_TOWER(new WorldPoint(2669, 3242, 0), KANDARIN, "Ground floor inside the Necromancer Tower. Easily accessed by using fairy ring code djp."),
KANDARIN_FIGHT_ARENA(new WorldPoint(2587, 3134, 0), KANDARIN, "South of the Fight Arena, north-west of the Nightmare Zone."),
KANDARIN_TREE_GNOME_VILLAGE(new WorldPoint(2526, 3160, 0), KANDARIN, "Tree Gnome Village, near the general store icon."),
KANDARIN_GRAVE_OF_SCORPIUS(new WorldPoint(2464, 3228, 0), KANDARIN, "Grave of Scorpius"),
KANDARIN_KHAZARD_BATTLEFIELD(new WorldPoint(2518, 3249, 0), KANDARIN, "Khazard Battlefield, in the small ruins south of tracker gnome 2."),
KANDARIN_KHAZARD_BATTLEFIELD(new WorldPoint(2518, 3249, 0), KANDARIN, "Khazard Battlefield, in the small ruins south of tracker gnome 2."),
KANDARIN_WEST_ARDY(new WorldPoint(2533, 3320, 0), KANDARIN, "West Ardougne, near the staircase outside the Civic Office."),
KANDARIN_SW_TREE_GNOME_STRONGHOLD(new WorldPoint(2411, 3431, 0), KANDARIN, "South-west Tree Gnome Stronghold"),
KANDARIN_OUTPOST(new WorldPoint(2458, 3364, 0), KANDARIN, "South of the Tree Gnome Stronghold, north-east of the Outpost."),
KANDARIN_BAXTORIAN_FALLS(new WorldPoint(2534, 3479, 0), KANDARIN, "South-east of Almera's house on Baxtorian Falls."),
KANDARIN_BA_AGILITY_COURSE(new WorldPoint(2536, 3546, 0), KANDARIN, "Inside the Barbarian Agility Course. Completion of Alfred Grimhand's Barcrawl is required."),
KANDARIN_SW_TREE_GNOME_STRONGHOLD(new WorldPoint(2411, 3431, 0), KANDARIN, "South-west Tree Gnome Stronghold"),
KANDARIN_OUTPOST(new WorldPoint(2458, 3364, 0), KANDARIN, "South of the Tree Gnome Stronghold, north-east of the Outpost."),
KANDARIN_BAXTORIAN_FALLS(new WorldPoint(2534, 3479, 0), KANDARIN, "South-east of Almera's house on Baxtorian Falls."),
KANDARIN_BA_AGILITY_COURSE(new WorldPoint(2536, 3546, 0), KANDARIN, "Inside the Barbarian Agility Course. Completion of Alfred Grimhand's Barcrawl is required."),
KARAMJA_MUSA_POINT(new WorldPoint(2914, 3168, 0), KARAMJA, "Musa Point, banana plantation."),
KARAMJA_BRIMHAVEN_FRUIT_TREE(new WorldPoint(2783, 3214, 0), KARAMJA, "Brimhaven, east of the fruit tree patch."),
KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2721, 3169, 0), KARAMJA, "West of Brimhaven."),
KARAMJA_GLIDER(new WorldPoint(2966, 2975, 0), KARAMJA, "West of the gnome glider."),
KARAMJA_KHARAZI_NE(new WorldPoint(2908, 2922, 0), KARAMJA, "North-eastern part of Kharazi Jungle."),
KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle."),
KARAMJA_CRASH_ISLAND(new WorldPoint(2910, 2737, 0), KARAMJA, "Northern part of Crash Island."),
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock."),
MISTHALIN_DRAYNOR_BANK(new WorldPoint(3096, 3235, 0), MISTHALIN, "South of Draynor Village bank."),
MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf."),
MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins."),
MORYTANIA_PORT_PHASMATYS(new WorldPoint(3613, 3485, 0), MORYTANIA, "West of Port Phasmatys, south-east of fairy ring."),
MORYTANIA_HOLLOWS(new WorldPoint(3500, 3423, 0), MORYTANIA, "Inside The Hollows, south of the bridge which was repaired in a quest."),
MORYTANIA_SWAMP(new WorldPoint(3422, 3374, 0), MORYTANIA, "Inside the Mort Myre Swamp, north-west of the Nature Grotto."),
MORYTANIA_HAUNTED_MINE(new WorldPoint(3441, 3259, 0), MORYTANIA, "At Haunted Mine quest start."),
MORYTANIA_MAUSOLEUM(new WorldPoint(3499, 3539, 0), MORYTANIA, "South of the Mausoleum."),
MORYTANIA_MOS_LES_HARMLESS(new WorldPoint(3744, 3041, 0), MORYTANIA, "Northern area of Mos Le'Harmless, between the lakes."),
MORYTANIA_MOS_LES_HARMLESS_BAR(new WorldPoint(3670, 2974, 0), MORYTANIA, "Near Mos Le'Harmless southern bar."),
MORYTANIA_DRAGONTOOTH_NORTH(new WorldPoint(3813, 3567, 0), MORYTANIA, "Northern part of Dragontooth Island."),
MORYTANIA_DRAGONTOOTH_SOUTH(new WorldPoint(3803, 3532, 0), MORYTANIA, "Southern part of Dragontooth Island."),
WESTERN_PROVINCE_EAGLES_PEAK(new WorldPoint(2297, 3530, 0), WESTERN_PROVINCE, "North-west of Eagles' Peak."),
KARAMJA_BRIMHAVEN_FRUIT_TREE(new WorldPoint(2783, 3214, 0), KARAMJA, "Brimhaven, east of the fruit tree patch."),
KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2721, 3169, 0), KARAMJA, "West of Brimhaven."),
KARAMJA_GLIDER(new WorldPoint(2966, 2975, 0), KARAMJA, "West of the gnome glider."),
KARAMJA_KHARAZI_NE(new WorldPoint(2908, 2922, 0), KARAMJA, "North-eastern part of Kharazi Jungle."),
KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle."),
KARAMJA_CRASH_ISLAND(new WorldPoint(2910, 2737, 0), KARAMJA, "Northern part of Crash Island."),
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock."),
MISTHALIN_DRAYNOR_BANK(new WorldPoint(3096, 3235, 0), MISTHALIN, "South of Draynor Village bank."),
MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf."),
MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins."),
MORYTANIA_PORT_PHASMATYS(new WorldPoint(3613, 3485, 0), MORYTANIA, "West of Port Phasmatys, south-east of fairy ring."),
MORYTANIA_HOLLOWS(new WorldPoint(3500, 3423, 0), MORYTANIA, "Inside The Hollows, south of the bridge which was repaired in a quest."),
MORYTANIA_SWAMP(new WorldPoint(3422, 3374, 0), MORYTANIA, "Inside the Mort Myre Swamp, north-west of the Nature Grotto."),
MORYTANIA_HAUNTED_MINE(new WorldPoint(3441, 3259, 0), MORYTANIA, "At Haunted Mine quest start."),
MORYTANIA_MAUSOLEUM(new WorldPoint(3499, 3539, 0), MORYTANIA, "South of the Mausoleum."),
MORYTANIA_MOS_LES_HARMLESS(new WorldPoint(3744, 3041, 0), MORYTANIA, "Northern area of Mos Le'Harmless, between the lakes."),
MORYTANIA_MOS_LES_HARMLESS_BAR(new WorldPoint(3670, 2974, 0), MORYTANIA, "Near Mos Le'Harmless southern bar."),
MORYTANIA_DRAGONTOOTH_NORTH(new WorldPoint(3813, 3567, 0), MORYTANIA, "Northern part of Dragontooth Island."),
MORYTANIA_DRAGONTOOTH_SOUTH(new WorldPoint(3803, 3532, 0), MORYTANIA, "Southern part of Dragontooth Island."),
WESTERN_PROVINCE_EAGLES_PEAK(new WorldPoint(2297, 3530, 0), WESTERN_PROVINCE, "North-west of Eagles' Peak."),
WESTERN_PROVINCE_PISCATORIS(new WorldPoint(2337, 3689, 0), WESTERN_PROVINCE, "Piscatoris Fishing Colony"),
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2361, 3566, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
WESTERN_PROVINCE_ARANDAR(new WorldPoint(2366, 3318, 0), WESTERN_PROVINCE, "South-west of the crystal gate to Arandar."),
WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2270, 3244, 0), WESTERN_PROVINCE, "East of Elf Camp."),
WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Elf Camp."),
WESTERN_PROVINCE_LLETYA(new WorldPoint(2335, 3166, 0), WESTERN_PROVINCE, "In Lletya."),
WESTERN_PROVINCE_TYRAS(new WorldPoint(2204, 3157, 0), WESTERN_PROVINCE, "Near Tyras Camp."),
WESTERN_PROVINCE_ZULANDRA(new WorldPoint(2196, 3057, 0), WESTERN_PROVINCE, "The northern house at Zul-Andra."),
WILDERNESS_5(new WorldPoint(3169, 3558, 0), WILDERNESS, "North of the Grand Exchange, level 5 Wilderness."),
WILDERNESS_12(new WorldPoint(3038, 3612, 0), WILDERNESS, "South-east of the Dark Warriors' Fortress, level 12 Wilderness."),
WILDERNESS_20(new WorldPoint(3225, 3676, 0), WILDERNESS, "East of the Corporeal Beast's lair, level 20 Wilderness."),
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2361, 3566, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
WESTERN_PROVINCE_ARANDAR(new WorldPoint(2366, 3318, 0), WESTERN_PROVINCE, "South-west of the crystal gate to Arandar."),
WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2270, 3244, 0), WESTERN_PROVINCE, "East of Elf Camp."),
WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Elf Camp."),
WESTERN_PROVINCE_LLETYA(new WorldPoint(2335, 3166, 0), WESTERN_PROVINCE, "In Lletya."),
WESTERN_PROVINCE_TYRAS(new WorldPoint(2204, 3157, 0), WESTERN_PROVINCE, "Near Tyras Camp."),
WESTERN_PROVINCE_ZULANDRA(new WorldPoint(2196, 3057, 0), WESTERN_PROVINCE, "The northern house at Zul-Andra."),
WILDERNESS_5(new WorldPoint(3169, 3558, 0), WILDERNESS, "North of the Grand Exchange, level 5 Wilderness."),
WILDERNESS_12(new WorldPoint(3038, 3612, 0), WILDERNESS, "South-east of the Dark Warriors' Fortress, level 12 Wilderness."),
WILDERNESS_20(new WorldPoint(3225, 3676, 0), WILDERNESS, "East of the Corporeal Beast's lair, level 20 Wilderness."),
WILDERNESS_27(new WorldPoint(3174, 3735, 0), WILDERNESS, "Inside the Ruins north of the Graveyard of Shadows, level 27 Wilderness."),
WILDERNESS_28(new WorldPoint(3374, 3734, 0), WILDERNESS, "East of Venenatis' nest, level 28 Wilderness."),
WILDERNESS_28(new WorldPoint(3374, 3734, 0), WILDERNESS, "East of Venenatis' nest, level 28 Wilderness."),
WILDERNESS_32(new WorldPoint(3311, 3773, 0), WILDERNESS, "North of Venenatis' nest, level 32 Wilderness."),
WILDERNESS_35(new WorldPoint(3153, 3795, 0), WILDERNESS, "East of the Wilderness canoe exit, level 35 Wilderness."),
WILDERNESS_37(new WorldPoint(2975, 3811, 0), WILDERNESS, "South-east of the Chaos Temple, level 37 Wilderness."),
WILDERNESS_38(new WorldPoint(3294, 3817, 0), WILDERNESS, "South of Callisto, level 38 Wilderness."),
WILDERNESS_49(new WorldPoint(3140, 3910, 0), WILDERNESS, "South-west of the Deserted Keep, level 49 Wilderness."),
WILDERNESS_54(new WorldPoint(2983, 3946, 0), WILDERNESS, "West of the Wilderness Agility Course, level 54 Wilderness."),
ZEAH_BLASTMINE_BANK(new WorldPoint(1507, 3856, 0), ZEAH, "Next to the bank in the Lovakengj blast mine."),
ZEAH_BLASTMINE_NORTH(new WorldPoint(1490, 3883, 0), ZEAH, "Northern part of the Lovakengj blast mine."),
ZEAH_LOVAKITE_FURNACE(new WorldPoint(1505, 3814, 0), ZEAH, "Next to the lovakite furnace in Lovakengj."),
ZEAH_LOVAKENGJ_MINE(new WorldPoint(1477, 3779, 0), ZEAH, "Next to mithril rock in the Lovakengj mine."),
ZEAH_SULPHR_MINE(new WorldPoint(1428, 3866, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine."),
WILDERNESS_35(new WorldPoint(3153, 3795, 0), WILDERNESS, "East of the Wilderness canoe exit, level 35 Wilderness."),
WILDERNESS_37(new WorldPoint(2975, 3811, 0), WILDERNESS, "South-east of the Chaos Temple, level 37 Wilderness."),
WILDERNESS_38(new WorldPoint(3294, 3817, 0), WILDERNESS, "South of Callisto, level 38 Wilderness."),
WILDERNESS_49(new WorldPoint(3140, 3910, 0), WILDERNESS, "South-west of the Deserted Keep, level 49 Wilderness."),
WILDERNESS_54(new WorldPoint(2983, 3946, 0), WILDERNESS, "West of the Wilderness Agility Course, level 54 Wilderness."),
ZEAH_BLASTMINE_BANK(new WorldPoint(1507, 3856, 0), ZEAH, "Next to the bank in the Lovakengj blast mine."),
ZEAH_BLASTMINE_NORTH(new WorldPoint(1490, 3883, 0), ZEAH, "Northern part of the Lovakengj blast mine."),
ZEAH_LOVAKITE_FURNACE(new WorldPoint(1505, 3814, 0), ZEAH, "Next to the lovakite furnace in Lovakengj."),
ZEAH_LOVAKENGJ_MINE(new WorldPoint(1477, 3779, 0), ZEAH, "Next to mithril rock in the Lovakengj mine."),
ZEAH_SULPHR_MINE(new WorldPoint(1428, 3866, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine."),
ZEAH_SHAYZIEN_BANK(new WorldPoint(1517, 3603, 0), ZEAH, "South-east of the bank in Shayzien."),
ZEAH_OVERPASS(new WorldPoint(1467, 3714, 0), ZEAH, "Overpass between Lovakengj and Shayzien."),
ZEAH_LIZARDMAN(new WorldPoint(1493, 3694, 0), ZEAH, "Within Lizardman Canyon, east of the ladder. Requires 5% favour with Shayzien."),
ZEAH_COMBAT_RING(new WorldPoint(1557, 3580, 0), ZEAH, "Shayzien, south-east of the Combat Ring."),
ZEAH_SHAYZIEN_BANK_2(new WorldPoint(1494, 3622, 0), ZEAH, "North-west of the bank in Shayzien."),
ZEAH_LIBRARY(new WorldPoint(1601, 3842, 0), ZEAH, "North-west of the Arceuus Library."),
ZEAH_HOUSECHURCH(new WorldPoint(1682, 3792, 0), ZEAH, "By the entrance to the Arceuus church."),
ZEAH_DARK_ALTAR(new WorldPoint(1699, 3879, 0), ZEAH, "West of the Dark Altar."),
ZEAH_OVERPASS(new WorldPoint(1467, 3714, 0), ZEAH, "Overpass between Lovakengj and Shayzien."),
ZEAH_LIZARDMAN(new WorldPoint(1493, 3694, 0), ZEAH, "Within Lizardman Canyon, east of the ladder. Requires 5% favour with Shayzien."),
ZEAH_COMBAT_RING(new WorldPoint(1557, 3580, 0), ZEAH, "Shayzien, south-east of the Combat Ring."),
ZEAH_SHAYZIEN_BANK_2(new WorldPoint(1494, 3622, 0), ZEAH, "North-west of the bank in Shayzien."),
ZEAH_LIBRARY(new WorldPoint(1601, 3842, 0), ZEAH, "North-west of the Arceuus Library."),
ZEAH_HOUSECHURCH(new WorldPoint(1682, 3792, 0), ZEAH, "By the entrance to the Arceuus church."),
ZEAH_DARK_ALTAR(new WorldPoint(1699, 3879, 0), ZEAH, "West of the Dark Altar."),
ZEAH_ARCEUUS_HOUSE(new WorldPoint(1708, 3701, 0), ZEAH, "By the southern entrance to Arceuus."),
ZEAH_ESSENCE_MINE(new WorldPoint(1762, 3852, 0), ZEAH, "By the Arceuus essence mine."),
ZEAH_ESSENCE_MINE_NE(new WorldPoint(1772, 3866, 0), ZEAH, "North-east of the Arceuus essence mine."),
ZEAH_PISCARILUS_MINE(new WorldPoint(1768, 3705, 0), ZEAH, "South of the Piscarilius mine."),
ZEAH_GOLDEN_FIELD_TAVERN(new WorldPoint(1718, 3647, 0), ZEAH, "South of The Golden Field tavern in the northern area of Hosidius."),
ZEAH_MESS_HALL(new WorldPoint(1658, 3621, 0), ZEAH, "East of the Mess hall."),
ZEAH_WATSONS_HOUSE(new WorldPoint(1653, 3573, 0), ZEAH, "East of Watson's house."),
ZEAH_VANNAHS_FARM_STORE(new WorldPoint(1806, 3521, 0), ZEAH, "North of Vannah's Farm Store, between the chicken coop and willow trees."),
ZEAH_ESSENCE_MINE(new WorldPoint(1762, 3852, 0), ZEAH, "By the Arceuus essence mine."),
ZEAH_ESSENCE_MINE_NE(new WorldPoint(1772, 3866, 0), ZEAH, "North-east of the Arceuus essence mine."),
ZEAH_PISCARILUS_MINE(new WorldPoint(1768, 3705, 0), ZEAH, "South of the Piscarilius mine."),
ZEAH_GOLDEN_FIELD_TAVERN(new WorldPoint(1718, 3647, 0), ZEAH, "South of The Golden Field tavern in the northern area of Hosidius."),
ZEAH_MESS_HALL(new WorldPoint(1658, 3621, 0), ZEAH, "East of the Mess hall."),
ZEAH_WATSONS_HOUSE(new WorldPoint(1653, 3573, 0), ZEAH, "East of Watson's house."),
ZEAH_VANNAHS_FARM_STORE(new WorldPoint(1806, 3521, 0), ZEAH, "North of Vannah's Farm Store, between the chicken coop and willow trees."),
ZEAH_FARMING_GUILD_W(new WorldPoint(1209, 3737, 0), ZEAH, "West of the Farming Guild."),
ZEAH_DAIRY_COW(new WorldPoint(1320, 3718, 0), ZEAH, "North-east of the Kebos Lowlands, east of the dairy cow."),
ZEAH_CRIMSON_SWIFTS(new WorldPoint(1186, 3583, 0), ZEAH, "South-west of the Kebos Swamp, below the crimson swifts.");

View File

@@ -46,8 +46,8 @@ public interface CookingConfig extends Config
@ConfigItem(
position = 2,
keyName = "fermentTimer",
name = "Show wine fermenting timer",
description = "Conifgures if the timer before wines are fermented is shown."
name = "Show wine ferment timer",
description = "Configures if the timer before wines are fermented is shown"
)
default boolean fermentTimer()
{

View File

@@ -29,8 +29,8 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.Duration;
import javax.inject.Inject;
import static net.runelite.api.AnimationID.COOKING_FIRE;
import static net.runelite.api.AnimationID.COOKING_RANGE;
@@ -71,7 +71,7 @@ class CookingOverlay extends Overlay
@Override
public Dimension render(Graphics2D graphics)
{
CookingSession session = plugin.getCookingSession();
CookingSession session = plugin.getSession();
if (session == null)
{
return null;

View File

@@ -28,23 +28,27 @@ package net.runelite.client.plugins.cooking;
import com.google.inject.Provides;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import static net.runelite.api.AnimationID.COOKING_WINE;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GraphicID;
import net.runelite.api.ItemID;
import net.runelite.api.Player;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.GraphicChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDependency;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@PluginDescriptor(
name = "Cooking",
@@ -61,19 +65,19 @@ public class CookingPlugin extends Plugin
private CookingConfig config;
@Inject
private CookingOverlay cookingOverlay;
@Inject
private FermentTimerOverlay fermentTimerOverlay;
private CookingOverlay overlay;
@Inject
private OverlayManager overlayManager;
@Getter(AccessLevel.PACKAGE)
private CookingSession cookingSession;
@Inject
private InfoBoxManager infoBoxManager;
@Inject
private ItemManager itemManager;
@Getter(AccessLevel.PACKAGE)
private FermentTimerSession fermentTimerSession;
private CookingSession session;
@Provides
CookingConfig getConfig(ConfigManager configManager)
@@ -84,69 +88,62 @@ public class CookingPlugin extends Plugin
@Override
protected void startUp() throws Exception
{
cookingSession = null;
fermentTimerSession = null;
overlayManager.add(cookingOverlay);
overlayManager.add(fermentTimerOverlay);
session = null;
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(fermentTimerOverlay);
overlayManager.remove(cookingOverlay);
fermentTimerSession = null;
cookingSession = null;
infoBoxManager.removeIf(FermentTimer.class::isInstance);
overlayManager.remove(overlay);
session = null;
}
@Subscribe
public void onGameTick(GameTick gameTick)
{
if (config.statTimeout() == 0)
if (session == null || config.statTimeout() == 0)
{
return;
}
if (cookingSession != null)
{
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
Duration sinceCut = Duration.between(cookingSession.getLastCookingAction(), Instant.now());
Duration sinceCut = Duration.between(session.getLastCookingAction(), Instant.now());
if (sinceCut.compareTo(statTimeout) >= 0)
{
cookingSession = null;
}
}
if (fermentTimerSession != null)
{
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
Duration sinceCut = Duration.between(fermentTimerSession.getLastWineMakingAction(), Instant.now());
if (sinceCut.compareTo(statTimeout) >= 0)
{
fermentTimerSession = null;
}
session = null;
}
}
@Subscribe
public void onAnimationChanged(AnimationChanged animationChanged)
public void onGraphicChanged(GraphicChanged graphicChanged)
{
Player localPlayer = client.getLocalPlayer();
Player player = client.getLocalPlayer();
if (localPlayer != animationChanged.getActor())
if (graphicChanged.getActor() != player)
{
return;
}
if (localPlayer.getAnimation() == COOKING_WINE && config.fermentTimer())
if (player.getGraphic() == GraphicID.WINE_MAKE && config.fermentTimer())
{
if (fermentTimerSession == null)
{
fermentTimerSession = new FermentTimerSession();
}
Optional<FermentTimer> fermentTimerOpt = infoBoxManager.getInfoBoxes().stream()
.filter(FermentTimer.class::isInstance)
.map(FermentTimer.class::cast)
.findAny();
fermentTimerSession.updateLastWineMakingAction();
if (fermentTimerOpt.isPresent())
{
FermentTimer fermentTimer = fermentTimerOpt.get();
fermentTimer.reset();
}
else
{
FermentTimer fermentTimer = new FermentTimer(itemManager.getImage(ItemID.JUG_OF_WINE), this);
infoBoxManager.addInfoBox(fermentTimer);
}
}
}
@@ -166,24 +163,24 @@ public class CookingPlugin extends Plugin
|| message.startsWith("You roast a")
|| message.startsWith("You cook"))
{
if (cookingSession == null)
if (session == null)
{
cookingSession = new CookingSession();
session = new CookingSession();
}
cookingSession.updateLastCookingAction();
cookingSession.increaseCookAmount();
session.updateLastCookingAction();
session.increaseCookAmount();
}
else if (message.startsWith("You accidentally burn"))
{
if (cookingSession == null)
if (session == null)
{
cookingSession = new CookingSession();
session = new CookingSession();
}
cookingSession.updateLastCookingAction();
cookingSession.increaseBurnAmount();
session.updateLastCookingAction();
session.increaseBurnAmount();
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2019, 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.cooking;
import java.awt.Color;
import java.awt.Image;
import java.time.Duration;
import java.time.Instant;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.InfoBox;
final class FermentTimer extends InfoBox
{
private static final Duration FERMENT_TIME = Duration.ofMillis(13_800);
private Instant fermentTime;
FermentTimer(Image image, Plugin plugin)
{
super(image, plugin);
reset();
}
@Override
public String getText()
{
int seconds = timeUntilFerment();
return Integer.toString(seconds);
}
@Override
public Color getTextColor()
{
int seconds = timeUntilFerment();
return seconds <= 3 ? Color.RED : Color.WHITE;
}
@Override
public boolean cull()
{
int seconds = timeUntilFerment();
return seconds <= 0;
}
void reset()
{
fermentTime = Instant.now().plus(FERMENT_TIME);
}
private int timeUntilFerment()
{
return (int) Duration.between(Instant.now(), fermentTime).getSeconds();
}
}

View File

@@ -1,104 +0,0 @@
/*
* Copyright (c) 2019, Lucas C <lucas1757@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.cooking;
import com.google.inject.Inject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.time.Duration;
import java.time.Instant;
import lombok.extern.slf4j.Slf4j;
import static net.runelite.api.AnimationID.COOKING_WINE;
import net.runelite.api.Client;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
@Slf4j
class FermentTimerOverlay extends Overlay
{
private static final int INITIAL_TIME = 12;
private final Client client;
private final CookingPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private FermentTimerOverlay(final Client client, final CookingPlugin plugin)
{
super(plugin);
setPosition(OverlayPosition.TOP_LEFT);
this.client = client;
this.plugin = plugin;
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Fermenting Timer overlay"));
}
@Override
public Dimension render(Graphics2D graphics)
{
FermentTimerSession session = plugin.getFermentTimerSession();
if (session == null)
{
return null;
}
panelComponent.getChildren().clear();
if (isMakingWine() || Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds() < INITIAL_TIME)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Making Wine")
.color(Color.GREEN)
.build());
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
tableComponent.addRow("Ferments in:", String.valueOf(INITIAL_TIME - Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds()));
panelComponent.getChildren().add(tableComponent);
}
else
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Wine Fermented")
.color(Color.ORANGE)
.build());
}
return panelComponent.render(graphics);
}
private boolean isMakingWine()
{
return (client.getLocalPlayer().getAnimation() == COOKING_WINE);
}
}

View File

@@ -489,6 +489,7 @@ class DevToolsOverlay extends Overlay
WidgetItem widgetItem = widget.getWidgetItem(itemIndex);
if (widgetItem == null
|| widgetItem.getId() < 0
|| widgetItem.getId() == ITEM_EMPTY
|| widgetItem.getId() == ITEM_FILLED)
{

View File

@@ -123,7 +123,7 @@ public class ExaminePlugin extends Plugin
int widgetChild = TO_CHILD(widgetId);
Widget widget = client.getWidget(widgetGroup, widgetChild);
WidgetItem widgetItem = widget.getWidgetItem(event.getActionParam());
quantity = widgetItem != null ? widgetItem.getQuantity() : 1;
quantity = widgetItem != null && widgetItem.getId() >= 0 ? widgetItem.getQuantity() : 1;
break;
}
case EXAMINE_ITEM_BANK_EQ:

View File

@@ -1,6 +1,5 @@
/*
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* Copyright (c) 2018, Lars <lars.oernlo@gmail.com>
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,53 +22,41 @@
* (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.mining;
package net.runelite.client.plugins.inventorygrid;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("mining")
public interface MiningConfig extends Config
@ConfigGroup("inventorygrid")
public interface InventoryGridConfig extends Config
{
@ConfigItem(
keyName = "showMiningRocks",
name = "Show rock mining spots",
description = "Configures whether or not the mining spots are displayed."
keyName = "showItem",
name = "Show item",
description = "Show a preview of the item in the new slot"
)
default boolean showMiningRocks()
default boolean showItem()
{
return true;
}
@ConfigItem(
keyName = "statTimeout",
name = "Reset stats (minutes)",
description = "Configures the time until statistics are reset"
keyName = "showGrid",
name = "Show grid",
description = "Show a grid on the inventory while dragging"
)
default int statTimeout()
{
return 5;
}
@ConfigItem(
keyName = "showMiningStats",
name = "Show mining session stats",
description = "Configures whether to display mining session stats"
)
default boolean showMiningStats()
default boolean showGrid()
{
return true;
}
@ConfigItem(
keyName = "showMiningState",
name = "Show current mining state",
description = "Shows current mining state. 'You are currently mining' / 'You are currently NOT mining'"
keyName = "showHighlight",
name = "Highlight background",
description = "Show a green background highlight on the new slot"
)
default boolean showMiningState()
default boolean showHighlight()
{
return true;
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,7 +23,7 @@
* (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.inventoryhighlight;
package net.runelite.client.plugins.inventorygrid;
import com.google.inject.Inject;
import java.awt.AlphaComposite;
@@ -35,105 +36,80 @@ import java.awt.image.BufferedImage;
import net.runelite.api.Client;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
public class InventoryHighlightOverlay extends Overlay
class InventoryGridOverlay extends Overlay
{
private final InventoryHighlightPlugin plugin;
private final InventoryHighlightConfig config;
private final Client client;
private final ItemManager itemManager;
// the inventory widget location is slightly off
private static final int FIXED_MARGIN_X = -10;
private static final int FIXED_MARGIN_Y = -25;
private static final int RESIZEABLE_MARGIN_X = -6;
private static final int RESIZEABLE_MARGIN_Y = -21;
private static final int ITEM_WIDTH = 32;
private static final int ITEM_HEIGHT = 32;
private static final int ITEM_MARGIN_X = 10;
private static final int ITEM_MARGIN_Y = 4;
private static final int INVENTORY_SIZE = 28;
private static final int DRAG_DELAY = 5;
private static final Color HIGHLIGHT = new Color(0, 255, 0, 45);
private static final Color GRID = new Color(255, 255, 255, 45);
private final InventoryGridConfig config;
private final Client client;
private final ItemManager itemManager;
@Inject
public InventoryHighlightOverlay(InventoryHighlightPlugin plugin, InventoryHighlightConfig config, Client client, ItemManager itemManager)
private InventoryGridOverlay(InventoryGridConfig config, Client client, ItemManager itemManager)
{
this.plugin = plugin;
this.itemManager = itemManager;
this.client = client;
this.config = config;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_WIDGETS);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (plugin.getDraggingItem() == -1 || !plugin.isDragging())
final Widget if1DraggingWidget = client.getIf1DraggedWidget();
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
if (if1DraggingWidget == null || if1DraggingWidget != inventoryWidget
|| client.getItemPressedDuration() < DRAG_DELAY)
{
return null;
}
int marginX, marginY;
if (client.isResized())
{
marginX = RESIZEABLE_MARGIN_X;
marginY = RESIZEABLE_MARGIN_Y;
}
else
{
marginX = FIXED_MARGIN_X;
marginY = FIXED_MARGIN_Y;
}
final net.runelite.api.Point mouse = client.getMouseCanvasPosition();
final Point updatedMouse = new Point(mouse.getX() + marginX, mouse.getY() + marginY);
final Point mousePoint = new Point(mouse.getX(), mouse.getY());
// null checks for inventory are checked during dragging events
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
final int inventoryX = inventoryWidget.getCanvasLocation().getX() + marginX;
final int inventoryY = inventoryWidget.getCanvasLocation().getY() + marginY;
final BufferedImage draggedItemImage = itemManager.getImage(plugin.getDraggingItem());
for (int i = 0; i < 4; i++)
for (int i = 0; i < INVENTORY_SIZE; ++i)
{
for (int j = 0; j < 7; j++)
{
final int x = (ITEM_WIDTH + ITEM_MARGIN_X) * i + inventoryX;
final int y = (ITEM_HEIGHT + ITEM_MARGIN_Y) * j + inventoryY;
final Rectangle bounds = new Rectangle(x, y, ITEM_WIDTH, ITEM_HEIGHT);
WidgetItem widgetItem = inventoryWidget.getWidgetItem(i);
if (config.showItem() && bounds.contains(updatedMouse))
final Rectangle bounds = widgetItem.getCanvasBounds();
boolean inBounds = bounds.contains(mousePoint);
if (config.showItem() && inBounds)
{
final WidgetItem draggedItem = inventoryWidget.getWidgetItem(client.getIf1DraggedItemIndex());
final BufferedImage draggedItemImage = itemManager.getImage(draggedItem.getId());
final int x = (int) bounds.getX();
final int y = (int) bounds.getY();
graphics.setComposite(AlphaComposite.SrcOver.derive(0.3f));
graphics.drawImage(draggedItemImage, x, y, null);
graphics.setComposite(AlphaComposite.SrcOver);
}
if (config.showHighlight() && bounds.contains(updatedMouse))
if (config.showHighlight() && inBounds)
{
graphics.setColor(HIGHLIGHT);
graphics.fill(bounds);
}
if (config.showGrid())
{
// don't set color on highlighted slot
if (!config.showHighlight() || !(config.showHighlight() && bounds.contains(updatedMouse)))
else if (config.showGrid())
{
graphics.setColor(GRID);
graphics.fill(bounds);
}
}
}
}
return null;
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,79 +23,44 @@
* (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.inventoryhighlight;
package net.runelite.client.plugins.inventorygrid;
import com.google.inject.Inject;
import com.google.inject.Provides;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.events.FocusChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.input.MouseManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Inventory Highlight",
description = "Shows a preview of where items will be dragged",
name = "Inventory Grid",
description = "Shows a grid over the inventory and a preview of where items will be dragged",
tags = {"items", "overlay"},
type = PluginType.UTILITY,
enabledByDefault = false
)
public class InventoryHighlightPlugin extends Plugin
public class InventoryGridPlugin extends Plugin
{
@Inject
private InventoryHighlightOverlay overlay;
@Inject
private InventoryHighlightInputListener inputListener;
@Inject
private MouseManager mouseManager;
private InventoryGridOverlay overlay;
@Inject
private OverlayManager overlayManager;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private int draggingItem = -1;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private boolean dragging = false;
@Override
public void startUp()
{
overlayManager.add(overlay);
mouseManager.registerMouseListener(inputListener);
}
@Override
public void shutDown()
{
mouseManager.unregisterMouseListener(inputListener);
overlayManager.remove(overlay);
}
@Provides
InventoryHighlightConfig getConfig(ConfigManager configManager)
InventoryGridConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(InventoryHighlightConfig.class);
}
@Subscribe
public void onFocusChanged(FocusChanged focusChanged)
{
if (!focusChanged.isFocused())
{
dragging = false;
draggingItem = -1;
}
return configManager.getConfig(InventoryGridConfig.class);
}
}

View File

@@ -1,53 +0,0 @@
package net.runelite.client.plugins.inventoryhighlight;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Stub;
@ConfigGroup("inventoryHighlight")
public interface InventoryHighlightConfig extends Config
{
@ConfigItem(
keyName = "showItem",
name = "Show the item",
description = "Show a preview of the item in the new slot"
)
default boolean showItem()
{
return true;
}
@ConfigItem(
keyName = "gridStub",
name = "Grid",
description = "",
position = 1
)
default Stub gridStub()
{
return new Stub();
}
@ConfigItem(
keyName = "showGrid",
name = "Show a grid",
description = "Show a grid on the inventory while dragging",
parent = "gridStub"
)
default boolean showGrid()
{
return false;
}
@ConfigItem(
keyName = "showHighlight",
name = "Show background highlight",
description = "Show a green background highlight in the new slot",
parent = "gridStub"
)
default boolean showHighlight()
{
return false;
}
}

View File

@@ -1,119 +0,0 @@
/*
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
* 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.inventoryhighlight;
import com.google.inject.Inject;
import java.awt.event.MouseEvent;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.Point;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.input.MouseListener;
public class InventoryHighlightInputListener implements MouseListener
{
private final InventoryHighlightPlugin plugin;
private final Client client;
@Inject
public InventoryHighlightInputListener(InventoryHighlightPlugin plugin, Client client)
{
this.plugin = plugin;
this.client = client;
}
@Override
public MouseEvent mouseDragged(MouseEvent mouseEvent)
{
plugin.setDragging(true);
return mouseEvent;
}
@Override
public MouseEvent mouseMoved(MouseEvent mouseEvent)
{
return mouseEvent;
}
@Override
public MouseEvent mouseClicked(MouseEvent mouseEvent)
{
return mouseEvent;
}
@Override
public MouseEvent mousePressed(MouseEvent mouseEvent)
{
if (client.getGameState() != GameState.LOGGED_IN)
{
return mouseEvent;
}
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
final Widget bankInventoryWidget = client.getWidget(WidgetInfo.BANK_INVENTORY_ITEMS_CONTAINER);
if ((inventoryWidget == null || inventoryWidget.isSelfHidden()) &&
(inventoryWidget == null || bankInventoryWidget == null || bankInventoryWidget.isSelfHidden()))
{
return mouseEvent;
}
final Point mouse = client.getMouseCanvasPosition();
for (WidgetItem item : inventoryWidget.getWidgetItems())
{
if (item.getCanvasBounds().contains(mouse.getX(), mouse.getY()))
{
plugin.setDraggingItem(item.getId());
break;
}
}
return mouseEvent;
}
@Override
public MouseEvent mouseReleased(MouseEvent mouseEvent)
{
plugin.setDragging(false);
plugin.setDraggingItem(-1);
return mouseEvent;
}
@Override
public MouseEvent mouseEntered(MouseEvent mouseEvent)
{
return mouseEvent;
}
@Override
public MouseEvent mouseExited(MouseEvent mouseEvent)
{
return mouseEvent;
}
}

View File

@@ -58,7 +58,7 @@ public class InventoryTagsOverlay extends WidgetItemOverlay
{
Rectangle bounds = itemWidget.getCanvasBounds();
final BufferedImage outline = itemManager.getItemOutline(itemId, itemWidget.getQuantity(), color);
graphics.drawImage(outline, (int) bounds.getX() + 1, (int) bounds.getY() + 1, null);
graphics.drawImage(outline, (int) bounds.getX(), (int) bounds.getY(), null);
}
}
}

View File

@@ -162,9 +162,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
final Rectangle bounds = itemWidget.getCanvasBounds();
final TextComponent textComponent = new TextComponent();
textComponent.setPosition(new
Point(bounds.x, bounds.y + 16));
textComponent.setPosition(new Point(bounds.x - 1, bounds.y + 15));
textComponent.setText(charges < 0 ? "?" : String.valueOf(charges));
textComponent.setColor(itemChargePlugin.getColor(charges));
textComponent.render(graphics);

View File

@@ -87,7 +87,7 @@ class ItemIdentificationOverlay extends WidgetItemOverlay
private void renderText(Graphics2D graphics, Rectangle bounds, ItemIdentification iden)
{
final TextComponent textComponent = new TextComponent();
textComponent.setPosition(new Point(bounds.x, bounds.y + bounds.height));
textComponent.setPosition(new Point(bounds.x - 1, bounds.y + bounds.height - 1));
textComponent.setColor(config.textColor());
switch (config.identificationType())
{

View File

@@ -22,7 +22,7 @@
* (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.wasdcamera;
package net.runelite.client.plugins.keyremapping;
import java.awt.event.KeyEvent;
import net.runelite.client.config.Config;
@@ -30,13 +30,24 @@ import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ModifierlessKeybind;
@ConfigGroup("wasdcamera")
public interface WASDCameraConfig extends Config
@ConfigGroup("keyremapping")
public interface KeyRemappingConfig extends Config
{
@ConfigItem(
position = 1,
keyName = "cameraRemap",
name = "Remap Camera",
description = "Configures whether the camera movement uses remapped keys"
)
default boolean cameraRemap()
{
return true;
}
@ConfigItem(
position = 2,
keyName = "up",
name = "Up key",
name = "Camera Up key",
description = "The key which will replace up."
)
default ModifierlessKeybind up()
@@ -45,9 +56,9 @@ public interface WASDCameraConfig extends Config
}
@ConfigItem(
position = 2,
position = 3,
keyName = "down",
name = "Down key",
name = "Camera Down key",
description = "The key which will replace down."
)
default ModifierlessKeybind down()
@@ -56,9 +67,9 @@ public interface WASDCameraConfig extends Config
}
@ConfigItem(
position = 3,
position = 4,
keyName = "left",
name = "Left key",
name = "Camera Left key",
description = "The key which will replace left."
)
default ModifierlessKeybind left()
@@ -67,13 +78,24 @@ public interface WASDCameraConfig extends Config
}
@ConfigItem(
position = 4,
position = 5,
keyName = "right",
name = "Right key",
name = "Camera Right key",
description = "The key which will replace right."
)
default ModifierlessKeybind right()
{
return new ModifierlessKeybind(KeyEvent.VK_D, 0);
}
@ConfigItem(
position = 6,
keyName = "fkeyRemap",
name = "Remap F Keys",
description = "Configures whether F-Keys are Remapped to 1 (F1) through 0 (F10), '-' (F11), and '=' (F12)"
)
default boolean fkeyRemap()
{
return false;
}
}

View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Abexlry <abexlry@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.keyremapping;
import com.google.common.base.Strings;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.VarClientStr;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.Keybind;
import net.runelite.client.config.ModifierlessKeybind;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.MouseAdapter;
class KeyRemappingListener extends MouseAdapter implements KeyListener
{
private static final Keybind ONE = new ModifierlessKeybind(KeyEvent.VK_1, 0);
private static final Keybind TWO = new ModifierlessKeybind(KeyEvent.VK_2, 0);
private static final Keybind THREE = new ModifierlessKeybind(KeyEvent.VK_3, 0);
private static final Keybind FOUR = new ModifierlessKeybind(KeyEvent.VK_4, 0);
private static final Keybind FIVE = new ModifierlessKeybind(KeyEvent.VK_5, 0);
private static final Keybind SIX = new ModifierlessKeybind(KeyEvent.VK_6, 0);
private static final Keybind SEVEN = new ModifierlessKeybind(KeyEvent.VK_7, 0);
private static final Keybind EIGHT = new ModifierlessKeybind(KeyEvent.VK_8, 0);
private static final Keybind NINE = new ModifierlessKeybind(KeyEvent.VK_9, 0);
private static final Keybind ZERO = new ModifierlessKeybind(KeyEvent.VK_0, 0);
private static final Keybind MINUS = new ModifierlessKeybind(KeyEvent.VK_MINUS, 0);
private static final Keybind EQUALS = new ModifierlessKeybind(KeyEvent.VK_EQUALS, 0);
@Inject
private KeyRemappingPlugin plugin;
@Inject
private KeyRemappingConfig config;
@Inject
private Client client;
@Inject
private ClientThread clientThread;
private final Map<Integer, Integer> modified = new HashMap<>();
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (client.getGameState() == GameState.LOGIN_SCREEN || !plugin.chatboxFocused())
{
return;
}
if (!plugin.isTyping())
{
if (config.cameraRemap())
{
if (config.up().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_UP);
e.setKeyCode(KeyEvent.VK_UP);
}
else if (config.down().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_DOWN);
e.setKeyCode(KeyEvent.VK_DOWN);
}
else if (config.left().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_LEFT);
e.setKeyCode(KeyEvent.VK_LEFT);
}
else if (config.right().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_RIGHT);
e.setKeyCode(KeyEvent.VK_RIGHT);
}
}
if (config.fkeyRemap())
{
if (ONE.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F1);
e.setKeyCode(KeyEvent.VK_F1);
}
else if (TWO.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F2);
e.setKeyCode(KeyEvent.VK_F2);
}
else if (THREE.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F3);
e.setKeyCode(KeyEvent.VK_F3);
}
else if (FOUR.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F4);
e.setKeyCode(KeyEvent.VK_F4);
}
else if (FIVE.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F5);
e.setKeyCode(KeyEvent.VK_F5);
}
else if (SIX.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F6);
e.setKeyCode(KeyEvent.VK_F6);
}
else if (SEVEN.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F7);
e.setKeyCode(KeyEvent.VK_F7);
}
else if (EIGHT.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F8);
e.setKeyCode(KeyEvent.VK_F8);
}
else if (NINE.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F9);
e.setKeyCode(KeyEvent.VK_F9);
}
else if (ZERO.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F10);
e.setKeyCode(KeyEvent.VK_F10);
}
else if (MINUS.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F11);
e.setKeyCode(KeyEvent.VK_F11);
}
else if (EQUALS.matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_F12);
e.setKeyCode(KeyEvent.VK_F12);
}
}
switch (e.getKeyCode())
{
case KeyEvent.VK_ENTER:
case KeyEvent.VK_SLASH:
case KeyEvent.VK_COLON:
// refocus chatbox
plugin.setTyping(true);
clientThread.invoke(plugin::unlockChat);
break;
}
}
else
{
switch (e.getKeyCode())
{
case KeyEvent.VK_ENTER:
plugin.setTyping(false);
clientThread.invoke(plugin::lockChat);
break;
case KeyEvent.VK_ESCAPE:
plugin.setTyping(false);
clientThread.invoke(() ->
{
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
plugin.lockChat();
});
break;
case KeyEvent.VK_BACK_SPACE:
if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT)))
{
plugin.setTyping(false);
clientThread.invoke(plugin::lockChat);
}
}
}
}
@Override
public void keyReleased(KeyEvent e)
{
if (client.getGameState() == GameState.LOGIN_SCREEN)
{
return;
}
if (plugin.chatboxFocused() && !plugin.isTyping())
{
modified.remove(e.getKeyCode());
if (config.cameraRemap())
{
if (config.up().matches(e))
{
e.setKeyCode(KeyEvent.VK_UP);
}
else if (config.down().matches(e))
{
e.setKeyCode(KeyEvent.VK_DOWN);
}
else if (config.left().matches(e))
{
e.setKeyCode(KeyEvent.VK_LEFT);
}
else if (config.right().matches(e))
{
e.setKeyCode(KeyEvent.VK_RIGHT);
}
}
if (config.fkeyRemap())
{
if (ONE.matches(e))
{
e.setKeyCode(KeyEvent.VK_F1);
}
else if (TWO.matches(e))
{
e.setKeyCode(KeyEvent.VK_F2);
}
else if (THREE.matches(e))
{
e.setKeyCode(KeyEvent.VK_F3);
}
else if (FOUR.matches(e))
{
e.setKeyCode(KeyEvent.VK_F4);
}
else if (FIVE.matches(e))
{
e.setKeyCode(KeyEvent.VK_F5);
}
else if (SIX.matches(e))
{
e.setKeyCode(KeyEvent.VK_F6);
}
else if (SEVEN.matches(e))
{
e.setKeyCode(KeyEvent.VK_F7);
}
else if (EIGHT.matches(e))
{
e.setKeyCode(KeyEvent.VK_F8);
}
else if (NINE.matches(e))
{
e.setKeyCode(KeyEvent.VK_F9);
}
else if (ZERO.matches(e))
{
e.setKeyCode(KeyEvent.VK_F10);
}
else if (MINUS.matches(e))
{
e.setKeyCode(KeyEvent.VK_F11);
}
else if (EQUALS.matches(e))
{
e.setKeyCode(KeyEvent.VK_F12);
}
}
}
else
{
// press d + enter + release d - causes the right arrow to never be released
Integer m = modified.get(e.getKeyCode());
if (m != null)
{
modified.remove(e.getKeyCode());
e.setKeyCode(m);
}
}
}
}

View File

@@ -23,7 +23,7 @@
* (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.wasdcamera;
package net.runelite.client.plugins.keyremapping;
import com.google.inject.Provides;
import java.awt.Color;
@@ -50,12 +50,12 @@ import net.runelite.client.ui.JagexColors;
import net.runelite.client.util.ColorUtil;
@PluginDescriptor(
name = "WASD Camera",
description = "Allows use of WASD keys for camera movement with 'Press Enter to Chat'",
tags = {"enter", "chat"},
name = "Key Remapping",
description = "Allows use of WASD keys for camera movement with 'Press Enter to Chat', and remapping number keys to F-keys",
tags = {"enter", "chat", "wasd", "camera"},
enabledByDefault = false
)
public class WASDCameraPlugin extends Plugin
public class KeyRemappingPlugin extends Plugin
{
private static final String PRESS_ENTER_TO_CHAT = "Press Enter to Chat...";
private static final String SCRIPT_EVENT_SET_CHATBOX_INPUT = "setChatboxInput";
@@ -74,7 +74,7 @@ public class WASDCameraPlugin extends Plugin
private KeyManager keyManager;
@Inject
private WASDCameraListener inputListener;
private KeyRemappingListener inputListener;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
@@ -111,9 +111,9 @@ public class WASDCameraPlugin extends Plugin
}
@Provides
WASDCameraConfig getConfig(ConfigManager configManager)
KeyRemappingConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(WASDCameraConfig.class);
return configManager.getConfig(KeyRemappingConfig.class);
}
boolean chatboxFocused()
@@ -127,8 +127,12 @@ public class WASDCameraPlugin extends Plugin
// the search box on the world map can be focused, and chat input goes there, even
// though the chatbox still has its key listener.
Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH);
return worldMapSearch == null || client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) != 1;
if (worldMapSearch != null && client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) == 1)
{
return false;
}
return true;
}
@Subscribe

View File

@@ -36,9 +36,9 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.events.GameStateChanged;
import net.runelite.client.events.SessionOpen;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.SessionOpen;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
@@ -54,6 +54,7 @@ public class LoginScreenPlugin extends Plugin implements KeyListener
{
private static final int MAX_USERNAME_LENGTH = 254;
private static final int MAX_PASSWORD_LENGTH = 20;
private static final int MAX_PIN_LENGTH = 6;
@Inject
private Client client;
@@ -163,7 +164,9 @@ public class LoginScreenPlugin extends Plugin implements KeyListener
@Override
public void keyPressed(KeyEvent e)
{
if (!config.pasteEnabled() || client.getGameState() != GameState.LOGIN_SCREEN)
if (!config.pasteEnabled() || (
client.getGameState() != GameState.LOGIN_SCREEN &&
client.getGameState() != GameState.LOGIN_SCREEN_AUTHENTICATOR))
{
return;
}
@@ -182,7 +185,10 @@ public class LoginScreenPlugin extends Plugin implements KeyListener
.toString()
.trim();
// 0 is username, 1 is password
switch (client.getLoginIndex())
{
// Username/password form
case 2:
if (client.getCurrentLoginField() == 0)
{
// Truncate data to maximum username length if necessary
@@ -193,6 +199,14 @@ public class LoginScreenPlugin extends Plugin implements KeyListener
// Truncate data to maximum password length if necessary
client.setPassword(data.substring(0, Math.min(data.length(), MAX_PASSWORD_LENGTH)));
}
break;
// Authenticator form
case 4:
// Truncate data to maximum OTP code length if necessary
client.setOtp(data.substring(0, Math.min(data.length(), MAX_PIN_LENGTH)));
break;
}
}
catch (UnsupportedFlavorException | IOException ex)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,97 +24,73 @@
*/
package net.runelite.client.plugins.mining;
import com.google.common.collect.ImmutableSet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.time.Duration;
import java.time.Instant;
import java.util.Set;
import java.util.Iterator;
import java.util.List;
import javax.inject.Inject;
import static net.runelite.api.AnimationID.*;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
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.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.ui.overlay.components.ProgressPieComponent;
class MiningOverlay extends Overlay
{
private static final Set<Integer> MINING_ANIMATION_IDS = ImmutableSet.of(
MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL,
MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT,
MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_ORN,
MINING_MOTHERLODE_INFERNAL
);
private final Client client;
private final MiningPlugin plugin;
private final MiningConfig config;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
MiningOverlay(Client client, MiningPlugin plugin, MiningConfig config)
private MiningOverlay(Client client, MiningPlugin plugin)
{
setPosition(OverlayPosition.TOP_LEFT);
this.client = client;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.plugin = plugin;
this.config = config;
this.client = client;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!plugin.isInMlm() || !config.showMiningStats())
List<RockRespawn> respawns = plugin.getRespawns();
if (respawns.isEmpty())
{
return null;
}
MiningSession session = plugin.getSession();
if (session.getLastPayDirtMined() == null)
Instant now = Instant.now();
for (Iterator<RockRespawn> it = respawns.iterator(); it.hasNext();)
{
RockRespawn rockRespawn = it.next();
float percent = (now.toEpochMilli() - rockRespawn.getStartTime().toEpochMilli()) / (float) rockRespawn.getRespawnTime();
WorldPoint worldPoint = rockRespawn.getWorldPoint();
LocalPoint loc = LocalPoint.fromWorld(client, worldPoint);
if (loc == null || percent > 1.0f)
{
it.remove();
continue;
}
Point point = Perspective.localToCanvas(client, loc, client.getPlane());
if (point == null)
{
it.remove();
continue;
}
ProgressPieComponent ppc = new ProgressPieComponent();
ppc.setBorderColor(Color.ORANGE);
ppc.setFill(Color.YELLOW);
ppc.setPosition(point);
ppc.setProgress(percent);
ppc.render(graphics);
}
return null;
}
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now());
if (sinceCut.compareTo(statTimeout) >= 0)
{
return null;
}
panelComponent.getChildren().clear();
if (config.showMiningState())
{
if (MINING_ANIMATION_IDS.contains(client.getLocalPlayer().getAnimation()))
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("Mining")
.color(Color.GREEN)
.build());
}
else
{
panelComponent.getChildren().add(TitleComponent.builder()
.text("NOT mining")
.color(Color.RED)
.build());
}
}
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
tableComponent.addRow("Pay-dirt mined:", Integer.toString(session.getTotalMined()));
tableComponent.addRow("Pay-dirt/hr:", session.getRecentMined() > 2 ? Integer.toString(session.getPerHour()) : "");
panelComponent.getChildren().add(tableComponent);
return panelComponent.render(graphics);
}
}

View File

@@ -1,7 +1,5 @@
/*
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Lars <lars.oernlo@gmail.com>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,63 +24,45 @@
*/
package net.runelite.client.plugins.mining;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.Set;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.ItemID;
import static net.runelite.api.ObjectID.ORE_VEIN_26661;
import static net.runelite.api.ObjectID.ORE_VEIN_26662;
import static net.runelite.api.ObjectID.ORE_VEIN_26663;
import static net.runelite.api.ObjectID.ORE_VEIN_26664;
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26665;
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26666;
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26667;
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26668;
import static net.runelite.api.ObjectID.EMPTY_WALL;
import net.runelite.api.WallObject;
import net.runelite.api.events.GameObjectChanged;
import net.runelite.api.events.GameObjectDespawned;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameStateChanged;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.WallObjectSpawned;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.task.Schedule;
import net.runelite.client.ui.overlay.OverlayManager;
@Slf4j
@PluginDescriptor(
name = "Mining",
description = "Show helpful information about Mining",
tags = {"mining", "skilling", "overlay"},
type = PluginType.SKILLING,
description = "Show ore respawn timers",
tags = {"overlay", "skilling", "timers"},
enabledByDefault = false
)
public class MiningPlugin extends Plugin
{
private static final Set<Integer> MOTHERLODE_MAP_REGIONS = ImmutableSet.of(14679, 14680, 14681, 14935, 14936, 14937, 15191, 15192, 15193);
private static final Set<Integer> MINE_SPOTS = ImmutableSet.of(ORE_VEIN_26661, ORE_VEIN_26662, ORE_VEIN_26663, ORE_VEIN_26664);
private static final Set<Integer> MLM_ORE_TYPES = ImmutableSet.of(ItemID.RUNITE_ORE, ItemID.ADAMANTITE_ORE,
ItemID.MITHRIL_ORE, ItemID.GOLD_ORE, ItemID.COAL, ItemID.GOLDEN_NUGGET);
private static final Set<Integer> MINING_ROCKS = ImmutableSet.of(
// another website says depleted rocks are 7468, 7469
// website says stoney 2902, 2962, 2963, 2964,
2231, 2257, 2584, 2704, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 3805, 3806, 3807, 3808, 4437, 4438, 4676, 6669, 6670, 6671, 6672, 6673, 7453, 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7467, 7470, 7484, 7485, 7486, 7487, 7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, 8727, 8828, 8829, 8830, 10079, 10080, 10081, 11441, 11924, 12590, 15127, 15128, 15213, 16464, 16514, 16515, 16521, 16522, 16523, 16524, 16534, 16535, 16545, 16549, 16550, 16998, 16999, 17042, 17043, 17064, 17065, 18817, 18840, 18952, 18953, 18954, 18961, 19849, 19969, 19970, 19971, 19972, 19973, 22665, 22667, 23280, 23281, 23640, 24146, 24147, 24148, 24557, 26873, 26874, 27984, 27985, 27987, 27988, 28596, 28597, 28752, 28753, 28890
//2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2231, 2257, 2328, 3042, 3043, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 4676, 6943, 6944, 6945, 6946, 6947, 6948, 9296, 9297, 9303, 9304, 9305, 9306, 9316, 9317, 9331, 9332, 9335, 9336, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 10583, 10584, 10585, 10586, 10587, 10944, 10945, 10946, 10947, 10948, 10949, 11165, 11166, 11167, 11168, 11169, 11170, 11171, 11172, 11173, 11174, 11175, 11176, 11177, 11178, 11179, 11180, 11181, 11182, 11183, 11184, 11185, 11186, 11187, 11188, 11189, 11190, 11191, 11192, 11193, 11194, 11195, 11424, 11425, 11426, 11427, 11428, 11429, 11430, 11431, 11432, 11433, 11434, 11435, 11436, 11437, 11438, 11439, 11440, 11441, 11442, 11443, 11444, 11552, 11553, 11554, 11555, 11556, 11557, 11915, 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927, 11928, 11929, 11930, 11931, 11932, 11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, 11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, 11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, 11965
//968, 1480, 1855, 4043, 4487, 7533, 9716, 21250, 1997, 2581, 2582, 2694, 2695, 2696, 2697, 2835, 2836, 2837, 2901, 2965, 3339, 3364, 4526, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4887, 5604, 5605, 5606, 5844, 5845, 5896, 5985, 5987, 6622, 6623, 6707, 6708, 6709, 7466, 8725, 8726, 8950, 8951, 8952, 9031, 9032, 10036, 10782, 10783, 10784, 10785, 10786, 10787, 10788, 11097, 11098, 11182, 11183, 11424, 11425, 12564, 12565, 12566, 12567, 12588, 12589, 12774, 14814, 14815, 14816, 14817, 15198, 15199, 15217, 15218, 15219, 15410, 15536, 15537, 16077, 16078, 16079, 16080, 16115, 16136, 16284, 16303, 17350, 17351, 17352, 17353, 17354, 17355, 17356, 17357, 17358, 17364, 17365, 17366, 17679, 17958, 17959, 17960, 17970, 17971, 17972, 18871, 18872, 18873, 19131, 21571, 21572, 21573, 22549, 22550, 22551, 23124, 23125, 23126, 23127, 23165, 23976, 23977, 23978, 23979, 23980, 23981, 24693, 24694, 24695, 24696, 24697, 24698, 24699, 24700, 24701, 24781, 25158, 25159, 25160, 25422, 25423, 26372, 26373, 26376, 26377, 26850, 26856, 28580, 29102, 29883, 29884, 29885, 30344, 30519, 30521, 30522, 30857, 30858, 31045, 31781, 31782, 31783, 31784, 31785, 31786, 31787, 31788, 31789
);
private static final int MAX_INVENTORY_SIZE = 28;
private static final int ROCK_DISTANCE = 14;
private static final int MINING_GUILD_REGION = 12183;
// private static final int SACK_LARGE_SIZE = 162;
// private static final int SACK_SIZE = 81;
//
// private static final int UPPER_FLOOR_HEIGHT = -500;
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@@ -90,278 +70,99 @@ public class MiningPlugin extends Plugin
@Inject
private MiningOverlay overlay;
@Inject
private MiningRocksOverlay rocksOverlay;
@Inject
private MiningConfig config;
@Inject
private Client client;
@Inject
private ClientThread clientThread;
@Getter(AccessLevel.PACKAGE)
private boolean inMlm;
@Getter(AccessLevel.PACKAGE)
private int curSackSize;
@Getter(AccessLevel.PACKAGE)
private int maxSackSize;
@Getter(AccessLevel.PACKAGE)
private Integer depositsLeft;
private MiningSession session;
@Getter(AccessLevel.PACKAGE)
private final Set<WallObject> veins = new HashSet<>();
@Getter(AccessLevel.PACKAGE)
private final Set<GameObject> rocks = new HashSet<>();
@Provides
MiningConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(MiningConfig.class);
}
private final List<RockRespawn> respawns = new ArrayList<>();
private boolean recentlyLoggedIn;
@Override
protected void startUp()
{
overlayManager.add(overlay);
overlayManager.add(rocksOverlay);
// overlayManager.add(motherlodeGemOverlay);
// overlayManager.add(motherlodeSackOverlay);
session = new MiningSession();
//inMlm = checkInMlm();
// if (inMlm)
// {
// clientThread.invokeLater(this::refreshSackValues);
// }
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
overlayManager.remove(rocksOverlay);
// overlayManager.remove(motherlodeGemOverlay);
// overlayManager.remove(motherlodeSackOverlay);
session = null;
// veins.clear();
rocks.clear();
// Widget sack = client.getWidget(WidgetInfo.MOTHERLODE_MINE);
// clientThread.invokeLater(() ->
// {
// if (sack != null && sack.isHidden())
// {
// sack.setHidden(false);
// }
// });
}
public MiningSession getSession()
{
return session;
}
// @Subscribe
// public void onVarbitChanged(VarbitChanged event)
// {
// if (inMlm)
// {
// refreshSackValues();
// }
// }
// @Subscribe
// public void onChatMessage(ChatMessage event)
// {
// if (!inMlm || event.getType() != ChatMessageType.FILTERED)
// {
// return;
// }
//
// String chatMessage = event.getMessage();
//
// switch (chatMessage)
// {
// case "You manage to mine some pay-dirt.":
// session.incrementPayDirtMined();
// break;
//
// case "You just found a Diamond!":
// session.incrementGemFound(ItemID.UNCUT_DIAMOND);
// break;
//
// case "You just found a Ruby!":
// session.incrementGemFound(ItemID.UNCUT_RUBY);
// break;
//
// case "You just found an Emerald!":
// session.incrementGemFound(ItemID.UNCUT_EMERALD);
// break;
//
// case "You just found a Sapphire!":
// session.incrementGemFound(ItemID.UNCUT_SAPPHIRE);
// break;
// }
// }
@Schedule(
period = 1,
unit = ChronoUnit.SECONDS
)
// public void checkMining()
// {
// if (!inMlm)
// {
// return;
// }
//
// depositsLeft = calculateDepositsLeft();
//
// Instant lastPayDirtMined = session.getLastPayDirtMined();
// if (lastPayDirtMined == null)
// {
// return;
// }
//
// // reset recentPayDirtMined if you haven't mined anything recently
// Duration statTimeout = Duration.ofMinutes(config.statTimeout());
// Duration sinceMined = Duration.between(lastPayDirtMined, Instant.now());
//
// if (sinceMined.compareTo(statTimeout) >= 0)
// {
// session.resetRecent();
// }
// }
@Subscribe
public void onGameObjectSpawned(GameObjectSpawned event)
{
GameObject gameObject = event.getGameObject();
if (MINING_ROCKS.contains(gameObject.getId()))
{
rocks.add(gameObject);
}
}
@Subscribe
public void onGameObjectChanged(GameObjectChanged event)
{
GameObject previous = event.getPrevious();
GameObject gameObject = event.getGameObject();
rocks.remove(previous);
if (MINING_ROCKS.contains(gameObject.getId()))
{
rocks.add(gameObject);
}
}
@Subscribe
public void onGameObjectDespawned(GameObjectDespawned event)
{
GameObject gameObject = event.getGameObject();
rocks.remove(gameObject);
respawns.clear();
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() == GameState.LOADING)
switch (event.getGameState())
{
// on region changes the tiles get set to null
rocks.clear();
case LOADING:
case HOPPING:
respawns.clear();
break;
case LOGGED_IN:
// After login rocks that are depleted will be changed,
// so wait for the next game tick before watching for
// rocks to deplete
recentlyLoggedIn = true;
break;
}
}
// private Integer calculateDepositsLeft()
// {
// if (maxSackSize == 0) // check if maxSackSize has been initialized
// {
// refreshSackValues();
// }
//
// double depositsLeft = 0;
// int nonPayDirtItems = 0;
//
// ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
// if (inventory == null)
// {
// return null;
// }
//
// Item[] result = inventory.getItems();
// assert result != null;
//
// for (Item item : result)
// {
// // Assume that MLM ores are being banked and exclude them from the check,
// // so the user doesn't see the Overlay switch between deposits left and N/A.
// //
// // Count other items at nonPayDirtItems so depositsLeft is calculated accordingly.
// if (item.getId() != ItemID.PAYDIRT && item.getId() != -1 && !MLM_ORE_TYPES.contains(item.getId()))
// {
// nonPayDirtItems += 1;
// }
// }
//
// double inventorySpace = MAX_INVENTORY_SIZE - nonPayDirtItems;
// double sackSizeRemaining = maxSackSize - curSackSize;
//
// if (inventorySpace > 0 && sackSizeRemaining > 0)
// {
// depositsLeft = Math.ceil(sackSizeRemaining / inventorySpace);
// }
// else if (inventorySpace == 0)
// {
// return null;
// }
//
// return (int) depositsLeft;
// }
//
// private boolean checkInMlm()
// {
// if (client.getGameState() != GameState.LOGGED_IN)
// {
// return false;
// }
//
// int[] currentMapRegions = client.getMapRegions();
//
// // Verify that all regions exist in MOTHERLODE_MAP_REGIONS
// for (int region : currentMapRegions)
// {
// if (!MOTHERLODE_MAP_REGIONS.contains(region))
// {
// return false;
// }
// }
//
// return true;
// }
//
// private void refreshSackValues()
// {
// curSackSize = client.getVar(Varbits.SACK_NUMBER);
// boolean sackUpgraded = client.getVar(Varbits.SACK_UPGRADED) == 1;
// maxSackSize = sackUpgraded ? SACK_LARGE_SIZE : SACK_SIZE;
// }
//
// /**
// * Checks if the given point is "upstairs" in the mlm.
// * The upper floor is actually on z=0.
// * @param localPoint
// * @return
// */
// boolean isUpstairs(LocalPoint localPoint)
// {
// return Perspective.getTileHeight(client, localPoint, 0) < UPPER_FLOOR_HEIGHT;
// }
@Subscribe
public void onGameTick(GameTick gameTick)
{
recentlyLoggedIn = false;
}
@Subscribe
public void onGameObjectDespawned(GameObjectDespawned event)
{
if (client.getGameState() != GameState.LOGGED_IN || recentlyLoggedIn)
{
return;
}
final GameObject object = event.getGameObject();
Rock rock = Rock.getRock(object.getId());
if (rock != null)
{
RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(inMiningGuild()).toMillis());
respawns.add(rockRespawn);
}
}
@Subscribe
public void onWallObjectSpawned(WallObjectSpawned event)
{
if (client.getGameState() != GameState.LOGGED_IN)
{
return;
}
final WallObject object = event.getWallObject();
switch (object.getId())
{
case EMPTY_WALL:
{
Rock rock = Rock.AMETHYST;
RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(inMiningGuild()).toMillis());
respawns.add(rockRespawn);
break;
}
case DEPLETED_VEIN_26665: // Depleted motherlode vein
case DEPLETED_VEIN_26666: // Depleted motherlode vein
case DEPLETED_VEIN_26667: // Depleted motherlode vein
case DEPLETED_VEIN_26668: // Depleted motherlode vein
{
Rock rock = Rock.ORE_VEIN;
RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(inMiningGuild()).toMillis());
respawns.add(rockRespawn);
break;
}
}
}
private boolean inMiningGuild()
{
return client.getLocalPlayer().getWorldLocation().getRegionID() == MINING_GUILD_REGION;
}
}

View File

@@ -1,115 +0,0 @@
/*
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Lars <lars.oernlo@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.mining;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.Skill;
import net.runelite.api.coords.LocalPoint;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
class MiningRocksOverlay extends Overlay
{
private static final int MAX_DISTANCE = 2350;
private final Client client;
private final MiningPlugin plugin;
private final MiningConfig config;
private final BufferedImage miningIcon;
@Inject
MiningRocksOverlay(Client client, MiningPlugin plugin, MiningConfig config, SkillIconManager iconManager)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client;
this.plugin = plugin;
this.config = config;
miningIcon = iconManager.getSkillImage(Skill.MINING);
}
@Override
public Dimension render(Graphics2D graphics)
{
Player local = client.getLocalPlayer();
renderTiles(graphics, local);
return null;
}
private void renderTiles(Graphics2D graphics, Player local)
{
LocalPoint localLocation = local.getLocalLocation();
if (config.showMiningRocks())
{
for (GameObject rock : plugin.getRocks())
{
LocalPoint location = rock.getLocalLocation();
if (localLocation.distanceTo(location) <= MAX_DISTANCE)
{
renderMiningRock(graphics, rock);
}
}
}
}
private void renderMiningRock(Graphics2D graphics, GameObject rock)
{
Point canvasLoc = Perspective.getCanvasImageLocation(client, rock.getLocalLocation(), miningIcon, 0);
if (canvasLoc != null)
{
graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null);
}
}
// private void renderMiningRockSquare(Graphics2D graphics, GameObject rock)
// {
// Polygon poly = Perspective.getCanvasTilePoly(client, rock.getLocalLocation());
//
// if (poly != null)
// {
// OverlayUtil.renderPolygon(graphics, poly, Color.red);
// }
// }
}

View File

@@ -1,139 +0,0 @@
/*
* 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.mining;
import java.time.Duration;
import java.time.Instant;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ItemID;
@Slf4j
public class MiningSession
{
private static final Duration HOUR = Duration.ofHours(1);
private int perHour;
private Instant lastPayDirtMined;
private int totalMined;
private Instant recentPayDirtMined;
private int recentMined;
@Getter(AccessLevel.PACKAGE)
private Instant lastGemFound;
@Getter(AccessLevel.PACKAGE)
private int diamondsFound;
@Getter(AccessLevel.PACKAGE)
private int rubiesFound;
@Getter(AccessLevel.PACKAGE)
private int emeraldsFound;
@Getter(AccessLevel.PACKAGE)
private int sapphiresFound;
public void incrementGemFound(int gemID)
{
lastGemFound = Instant.now();
switch (gemID)
{
case ItemID.UNCUT_DIAMOND:
diamondsFound++;
break;
case ItemID.UNCUT_RUBY:
rubiesFound++;
break;
case ItemID.UNCUT_EMERALD:
emeraldsFound++;
break;
case ItemID.UNCUT_SAPPHIRE:
sapphiresFound++;
break;
default:
log.error("Invalid gem type specified. The gem count will not be incremented.");
}
}
public void incrementPayDirtMined()
{
Instant now = Instant.now();
lastPayDirtMined = now;
++totalMined;
if (recentMined == 0)
{
recentPayDirtMined = now;
}
++recentMined;
Duration timeSinceStart = Duration.between(recentPayDirtMined, now);
if (!timeSinceStart.isZero())
{
perHour = (int) ((double) recentMined * (double) HOUR.toMillis() / (double) timeSinceStart.toMillis());
}
}
public void resetRecent()
{
recentPayDirtMined = null;
recentMined = 0;
}
public int getPerHour()
{
return perHour;
}
public Instant getLastPayDirtMined()
{
return lastPayDirtMined;
}
public int getTotalMined()
{
return totalMined;
}
public Instant getRecentPayDirtMined()
{
return recentPayDirtMined;
}
public int getRecentMined()
{
return recentMined;
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2019, 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.mining;
import com.google.common.collect.ImmutableMap;
import java.time.Duration;
import java.util.Map;
import static net.runelite.api.ObjectID.ROCKS_11161;
import static net.runelite.api.ObjectID.ROCKS_11360;
import static net.runelite.api.ObjectID.ROCKS_11361;
import static net.runelite.api.ObjectID.ROCKS_11364;
import static net.runelite.api.ObjectID.ROCKS_11365;
import static net.runelite.api.ObjectID.ROCKS_11366;
import static net.runelite.api.ObjectID.ROCKS_11367;
import static net.runelite.api.ObjectID.ROCKS_11369;
import static net.runelite.api.ObjectID.ROCKS_11370;
import static net.runelite.api.ObjectID.ROCKS_11371;
import static net.runelite.api.ObjectID.ROCKS_11372;
import static net.runelite.api.ObjectID.ROCKS_11373;
import static net.runelite.api.ObjectID.ROCKS_11374;
import static net.runelite.api.ObjectID.ROCKS_11375;
import static net.runelite.api.ObjectID.ROCKS_11376;
import static net.runelite.api.ObjectID.ROCKS_11377;
enum Rock
{
TIN(Duration.ofMillis(2300), ROCKS_11360, ROCKS_11361),
COPPER(Duration.ofMillis(2200), ROCKS_11161),
IRON(Duration.ofMillis(5300), ROCKS_11364, ROCKS_11365)
{
@Override
Duration getRespawnTime(boolean inMiningGuild)
{
return inMiningGuild ? Duration.ofMillis(2200) : super.respawnTime;
}
},
COAL(Duration.ofSeconds(40), ROCKS_11366, ROCKS_11367)
{
@Override
Duration getRespawnTime(boolean inMiningGuild)
{
return inMiningGuild ? Duration.ofMillis(14_500) : super.respawnTime;
}
},
SILVER(Duration.ofMinutes(1), ROCKS_11369),
GOLD(Duration.ofMinutes(1), ROCKS_11370, ROCKS_11371),
MITHRIL(Duration.ofMinutes(2), ROCKS_11372, ROCKS_11373)
{
@Override
Duration getRespawnTime(boolean inMiningGuild)
{
return inMiningGuild ? Duration.ofMinutes(1) : super.respawnTime;
}
},
ADAMANTITE(Duration.ofMinutes(4), ROCKS_11374, ROCKS_11375)
{
@Override
Duration getRespawnTime(boolean inMiningGuild)
{
return inMiningGuild ? Duration.ofMinutes(2) : super.respawnTime;
}
},
RUNITE(Duration.ofMinutes(12), ROCKS_11376, ROCKS_11377)
{
@Override
Duration getRespawnTime(boolean inMiningGuild)
{
return inMiningGuild ? Duration.ofMinutes(6) : super.respawnTime;
}
},
ORE_VEIN(Duration.ofSeconds(108)),
AMETHYST(Duration.ofSeconds(75));
private static final Map<Integer, Rock> ROCKS;
static
{
ImmutableMap.Builder<Integer, Rock> builder = new ImmutableMap.Builder<>();
for (Rock rock : values())
{
for (int id : rock.ids)
{
builder.put(id, rock);
}
}
ROCKS = builder.build();
}
private final Duration respawnTime;
private final int[] ids;
Rock(Duration respawnTime, int... ids)
{
this.respawnTime = respawnTime;
this.ids = ids;
}
Duration getRespawnTime(boolean inMiningGuild)
{
return respawnTime;
}
static Rock getRock(int id)
{
return ROCKS.get(id);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Lucas C <lucas1757@gmail.com>
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,19 +22,19 @@
* (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.cooking;
package net.runelite.client.plugins.mining;
import java.time.Instant;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.coords.WorldPoint;
class FermentTimerSession
@AllArgsConstructor
@Getter
class RockRespawn
{
@Getter(AccessLevel.PACKAGE)
private Instant lastWineMakingAction;
void updateLastWineMakingAction()
{
this.lastWineMakingAction = Instant.now();
}
private final Rock rock;
private final WorldPoint worldPoint;
private final Instant startTime;
private final int respawnTime;
}

View File

@@ -123,6 +123,8 @@ public class MusicListPlugin extends Plugin
return;
}
header.deleteAllChildren();
//Creation of the search and toggle status buttons
musicSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
musicSearchButton.setSpriteId(SpriteID.GE_SEARCH);

View File

@@ -134,6 +134,8 @@ public class QuestListPlugin extends Plugin
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);

View File

@@ -118,13 +118,13 @@ public class RunepouchOverlay extends WidgetItemOverlay
}
graphics.setColor(Color.black);
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 13 : 6),
location.getY() + 14 + (graphics.getFontMetrics().getHeight() - 1) * i);
graphics.setColor(config.fontColor());
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 12 : 5),
location.getY() + 13 + (graphics.getFontMetrics().getHeight() - 1) * i);
graphics.setColor(config.fontColor());
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 11 : 4),
location.getY() + 12 + (graphics.getFontMetrics().getHeight() - 1) * i);
if (!config.showIcons())
{
continue;
@@ -134,7 +134,7 @@ public class RunepouchOverlay extends WidgetItemOverlay
if (image != null)
{
OverlayUtil.renderImageLocation(graphics,
new Point(location.getX(), location.getY() + graphics.getFontMetrics().getHeight() * i),
new Point(location.getX() - 1, location.getY() + graphics.getFontMetrics().getHeight() * i - 1),
image);
}
}

View File

@@ -124,8 +124,8 @@ class SlayerOverlay extends WidgetItemOverlay
textComponent.setText(String.valueOf(amount));
// Draw the counter in the top left for equipment, and bottom left for jewelry
textComponent.setPosition(new Point(bounds.x, bounds.y + (SLAYER_JEWELRY.contains(itemId)
// Draw the counter in the bottom left for equipment, and top left for jewelry
textComponent.setPosition(new Point(bounds.x - 1, bounds.y - 1 + (SLAYER_JEWELRY.contains(itemId)
? bounds.height
: graphics.getFontMetrics().getHeight())));
textComponent.render(graphics);

View File

@@ -1,177 +0,0 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* Copyright (c) 2018, Abexlry <abexlry@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.wasdcamera;
import com.google.common.base.Strings;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.VarClientStr;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.MouseAdapter;
class WASDCameraListener extends MouseAdapter implements KeyListener
{
@Inject
private WASDCameraPlugin plugin;
@Inject
private WASDCameraConfig config;
@Inject
private Client client;
@Inject
private ClientThread clientThread;
private final Map<Integer, Integer> modified = new HashMap<>();
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (client.getGameState() != GameState.LOGGED_IN || !plugin.chatboxFocused())
{
return;
}
if (!plugin.isTyping())
{
if (config.up().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_UP);
e.setKeyCode(KeyEvent.VK_UP);
}
else if (config.down().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_DOWN);
e.setKeyCode(KeyEvent.VK_DOWN);
}
else if (config.left().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_LEFT);
e.setKeyCode(KeyEvent.VK_LEFT);
}
else if (config.right().matches(e))
{
modified.put(e.getKeyCode(), KeyEvent.VK_RIGHT);
e.setKeyCode(KeyEvent.VK_RIGHT);
}
else
{
switch (e.getKeyCode())
{
case KeyEvent.VK_ENTER:
case KeyEvent.VK_SLASH:
case KeyEvent.VK_COLON:
// refocus chatbox
plugin.setTyping(true);
clientThread.invoke(() ->
{
plugin.unlockChat();
});
break;
}
}
}
else
{
switch (e.getKeyCode())
{
case KeyEvent.VK_ENTER:
plugin.setTyping(false);
clientThread.invoke(() ->
{
plugin.lockChat();
});
break;
case KeyEvent.VK_ESCAPE:
plugin.setTyping(false);
clientThread.invoke(() ->
{
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
plugin.lockChat();
});
break;
case KeyEvent.VK_BACK_SPACE:
if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT)))
{
plugin.setTyping(false);
clientThread.invoke(() -> plugin.lockChat());
}
}
}
}
@Override
public void keyReleased(KeyEvent e)
{
if (client.getGameState() != GameState.LOGGED_IN)
{
return;
}
if (plugin.chatboxFocused() && !plugin.isTyping())
{
modified.remove(e.getKeyCode());
if (config.up().matches(e))
{
e.setKeyCode(KeyEvent.VK_UP);
}
else if (config.down().matches(e))
{
e.setKeyCode(KeyEvent.VK_DOWN);
}
else if (config.left().matches(e))
{
e.setKeyCode(KeyEvent.VK_LEFT);
}
else if (config.right().matches(e))
{
e.setKeyCode(KeyEvent.VK_RIGHT);
}
}
else
{
// press d + enter + release d - causes the right arrow to never be released
Integer m = modified.get(e.getKeyCode());
if (m != null)
{
modified.remove(e.getKeyCode());
e.setKeyCode(m);
}
}
}
}

View File

@@ -3314,7 +3314,7 @@
"21521": 250,
"21543": 13000,
"21545": 13000,
"21555": 18000,
"21555": 30000,
"21622": 13000,
"21634": 8,
"21637": 5,

View File

@@ -30,14 +30,23 @@ import com.google.inject.testing.fieldbinder.BoundFieldModule;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GraphicID;
import net.runelite.api.Player;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GraphicChanged;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Matchers.any;
import org.mockito.Mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
@@ -60,6 +69,14 @@ public class CookingPluginTest
@Bind
Client client;
@Mock
@Bind
InfoBoxManager infoBoxManager;
@Mock
@Bind
ItemManager itemManager;
@Mock
@Bind
CookingConfig config;
@@ -68,10 +85,6 @@ public class CookingPluginTest
@Bind
CookingOverlay cookingOverlay;
@Mock
@Bind
FermentTimerOverlay fermentTimerOverlay;
@Mock
@Bind
OverlayManager overlayManager;
@@ -91,8 +104,24 @@ public class CookingPluginTest
cookingPlugin.onChatMessage(chatMessage);
}
CookingSession cookingSession = cookingPlugin.getCookingSession();
CookingSession cookingSession = cookingPlugin.getSession();
assertNotNull(cookingSession);
assertEquals(COOKING_MESSAGES.length, cookingSession.getCookAmount());
}
@Test
public void testOnGraphicChanged()
{
Player player = mock(Player.class);
when(player.getGraphic()).thenReturn(GraphicID.WINE_MAKE);
when(config.fermentTimer()).thenReturn(true);
when(client.getLocalPlayer()).thenReturn(player);
GraphicChanged graphicChanged = new GraphicChanged();
graphicChanged.setActor(player);
cookingPlugin.onGraphicChanged(graphicChanged);
verify(infoBoxManager).addInfoBox(any(FermentTimer.class));
}
}

View File

@@ -26,12 +26,10 @@ package net.runelite.mixins;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.Actor;
import net.runelite.api.CollisionData;
import net.runelite.api.CollisionDataFlag;
import net.runelite.api.Constants;
import net.runelite.api.DecorativeObject;
import net.runelite.api.GameObject;
import net.runelite.api.GroundObject;
import net.runelite.api.Item;
import net.runelite.api.ItemLayer;
@@ -59,13 +57,18 @@ import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSActor;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSDeque;
import net.runelite.rs.api.RSGameObject;
import net.runelite.rs.api.RSGraphicsObject;
import net.runelite.rs.api.RSItem;
import net.runelite.rs.api.RSItemLayer;
import net.runelite.rs.api.RSNode;
import net.runelite.rs.api.RSProjectile;
import net.runelite.rs.api.RSRenderable;
import net.runelite.rs.api.RSTile;
import org.slf4j.Logger;
@Mixin(RSTile.class)
public abstract class RSTileMixin implements RSTile
@@ -73,9 +76,6 @@ public abstract class RSTileMixin implements RSTile
@Shadow("clientInstance")
private static RSClient client;
@Inject
private static GameObject lastGameObject;
@Inject
private static RSDeque[][][] lastGroundItems = new RSDeque[Constants.MAX_Z][Constants.SCENE_SIZE][Constants.SCENE_SIZE];
@@ -89,7 +89,7 @@ public abstract class RSTileMixin implements RSTile
private GroundObject previousGroundObject;
@Inject
private GameObject[] previousGameObjects;
private RSGameObject[] previousGameObjects;
@Inject
@Override
@@ -222,49 +222,77 @@ public abstract class RSTileMixin implements RSTile
if (previousGameObjects == null)
{
previousGameObjects = new GameObject[5];
previousGameObjects = new RSGameObject[5];
}
// Previous game object
GameObject previous = previousGameObjects[idx];
RSGameObject previous = previousGameObjects[idx];
// GameObject that was changed.
RSGameObject current = (RSGameObject) getGameObjects()[idx];
// Last game object
GameObject last = lastGameObject;
// Update last game object
lastGameObject = current;
// Update previous object to current
previousGameObjects[idx] = current;
// Duplicate event, return
if (current != null && current.equals(last))
if (current == previous)
{
return;
}
// Characters seem to generate a constant stream of new GameObjects
if (current == null || !(current.getRenderable() instanceof Actor))
// actors, projectiles, and graphics objects are added and removed from the scene each frame as GameObjects,
// so ignore them.
boolean currentInvalid = false, prevInvalid = false;
if (current != null)
{
if (current == null && previous != null)
RSRenderable renderable = current.getRenderable();
currentInvalid = renderable instanceof RSActor || renderable instanceof RSProjectile || renderable instanceof RSGraphicsObject;
}
if (previous != null)
{
RSRenderable renderable = previous.getRenderable();
prevInvalid = renderable instanceof RSActor || renderable instanceof RSProjectile || renderable instanceof RSGraphicsObject;
}
Logger logger = client.getLogger();
if (current == null)
{
if (prevInvalid)
{
return;
}
logger.trace("Game object despawn: {}", previous.getId());
GameObjectDespawned gameObjectDespawned = new GameObjectDespawned();
gameObjectDespawned.setTile(this);
gameObjectDespawned.setGameObject(previous);
client.getCallbacks().post(gameObjectDespawned);
}
else if (current != null && previous == null)
else if (previous == null)
{
if (currentInvalid)
{
return;
}
logger.trace("Game object spawn: {}", current.getId());
GameObjectSpawned gameObjectSpawned = new GameObjectSpawned();
gameObjectSpawned.setTile(this);
gameObjectSpawned.setGameObject(current);
client.getCallbacks().post(gameObjectSpawned);
}
else if (current != null && previous != null)
else
{
if (currentInvalid && prevInvalid)
{
return;
}
logger.trace("Game object change: {} -> {}", previous.getId(), current.getId());
GameObjectChanged gameObjectsChanged = new GameObjectChanged();
gameObjectsChanged.setTile(this);
gameObjectsChanged.setPrevious(previous);
@@ -272,7 +300,6 @@ public abstract class RSTileMixin implements RSTile
client.getCallbacks().post(gameObjectsChanged);
}
}
}
@FieldHook("itemLayer")
@Inject

View File

@@ -258,6 +258,11 @@ public abstract class RSWidgetMixin implements RSWidget
for (int i = 0; i < itemIds.length; ++i)
{
if (itemIds[i] <= 0)
{
continue;
}
WidgetItem item = getWidgetItem(i);
if (item != null)
@@ -287,19 +292,17 @@ public abstract class RSWidgetMixin implements RSWidget
int itemId = itemIds[index];
int itemQuantity = itemQuantities[index];
Point widgetCanvasLocation = getCanvasLocation();
if (itemId <= 0 || itemQuantity <= 0 || columns <= 0)
if (columns <= 0)
{
return null;
}
int row = index / columns;
int col = index % columns;
int itemX = widgetCanvasLocation.getX() + ((ITEM_SLOT_SIZE + xPitch) * col);
int itemY = widgetCanvasLocation.getY() + ((ITEM_SLOT_SIZE + yPitch) * row);
int itemX = rl$x + ((ITEM_SLOT_SIZE + xPitch) * col);
int itemY = rl$y + ((ITEM_SLOT_SIZE + yPitch) * row);
Rectangle bounds = new Rectangle(itemX - 1, itemY - 1, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
Rectangle bounds = new Rectangle(itemX, itemY, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
return new WidgetItem(itemId - 1, itemQuantity, index, bounds, this);
}

View File

@@ -248,10 +248,18 @@ public interface RSClient extends RSGameEngine, Client
@Override
void setPassword(String password);
@Import("otp")
@Override
void setOtp(String otp);
@Import("currentLoginField")
@Override
int getCurrentLoginField();
@Import("loginIndex")
@Override
int getLoginIndex();
@Import("playerOptions")
@Override
String[] getPlayerOptions();
@@ -772,6 +780,7 @@ public interface RSClient extends RSGameEngine, Client
boolean isInInstancedRegion();
@Import("itemPressedDuration")
@Override
int getItemPressedDuration();
@Import("itemPressedDuration")
@@ -927,6 +936,14 @@ public interface RSClient extends RSGameEngine, Client
@Import("endY")
int getEndY();
@Import("if1DraggedWidget")
@Override
RSWidget getIf1DraggedWidget();
@Import("if1DraggedItemIndex")
@Override
int getIf1DraggedItemIndex();
@Import("spellSelected")
@Override
void setSpellSelected(boolean selected);