Merge remote-tracking branch 'upstream/master' into master

This commit is contained in:
ThatGamerBlue
2021-04-26 17:36:22 +01:00
28 changed files with 553 additions and 80 deletions

View File

@@ -101,6 +101,7 @@ public final class AnimationID
public static final int SMITHING_SMELTING = 899; public static final int SMITHING_SMELTING = 899;
public static final int SMITHING_CANNONBALL = 827; //cball smithing uses this and SMITHING_SMELTING public static final int SMITHING_CANNONBALL = 827; //cball smithing uses this and SMITHING_SMELTING
public static final int SMITHING_ANVIL = 898; public static final int SMITHING_ANVIL = 898;
public static final int SMITHING_IMCANDO_HAMMER = 8911;
public static final int FISHING_BIG_NET = 620; public static final int FISHING_BIG_NET = 620;
public static final int FISHING_NET = 621; public static final int FISHING_NET = 621;
public static final int FISHING_POLE_CAST = 623; // pole is in the water public static final int FISHING_POLE_CAST = 623; // pole is in the water
@@ -205,6 +206,7 @@ public final class AnimationID
public static final int LEAGUE_HOME_TELEPORT_6 = 8807; public static final int LEAGUE_HOME_TELEPORT_6 = 8807;
public static final int CONSTRUCTION = 3676; public static final int CONSTRUCTION = 3676;
public static final int CONSTRUCTION_IMCANDO = 8192;
public static final int SAND_COLLECTION = 895; public static final int SAND_COLLECTION = 895;
public static final int PISCARILIUS_CRANE_REPAIR = 7199; public static final int PISCARILIUS_CRANE_REPAIR = 7199;
public static final int HOME_MAKE_TABLET = 4067; public static final int HOME_MAKE_TABLET = 4067;

View File

@@ -2174,4 +2174,19 @@ public interface Client extends GameEngine
* use createBuffer to create a new byte buffer * use createBuffer to create a new byte buffer
*/ */
Buffer createBuffer(byte[] initialBytes); Buffer createBuffer(byte[] initialBytes);
/**
* Get the list of message ids for the recently received cross-world messages. The upper 32 bits of the
* id is the world id, the lower is a sequence number per-world.
*
* @return
*/
long[] getCrossWorldMessageIds();
/**
* Get the index of the next message to be inserted in the cross world message id list
*
* @return
*/
int getCrossWorldMessageIdsIndex();
} }

View File

@@ -38,6 +38,13 @@ public interface PlayerComposition
*/ */
boolean isFemale(); boolean isFemale();
/**
* Get the body part colors for this player composition.
*
* @return an array of the colors, always size 5
*/
int[] getColors();
/** /**
* Gets an array of IDs related to equipment slots. * Gets an array of IDs related to equipment slots.
* <p> * <p>

View File

@@ -433,7 +433,8 @@ public enum WidgetInfo
EXPERIENCE_TRACKER_WIDGET(WidgetID.EXPERIENCE_TRACKER_GROUP_ID, WidgetID.ExperienceTracker.WIDGET), EXPERIENCE_TRACKER_WIDGET(WidgetID.EXPERIENCE_TRACKER_GROUP_ID, WidgetID.ExperienceTracker.WIDGET),
EXPERIENCE_TRACKER_BOTTOM_BAR(WidgetID.EXPERIENCE_TRACKER_GROUP_ID, WidgetID.ExperienceTracker.BOTTOM_BAR), EXPERIENCE_TRACKER_BOTTOM_BAR(WidgetID.EXPERIENCE_TRACKER_GROUP_ID, WidgetID.ExperienceTracker.BOTTOM_BAR),
FISHING_TRAWLER_TIMER(WidgetID.FISHING_TRAWLER_GROUP_ID, 14), FISHING_TRAWLER_CONTRIBUTION(WidgetID.FISHING_TRAWLER_GROUP_ID, 14),
FISHING_TRAWLER_TIMER(WidgetID.FISHING_TRAWLER_GROUP_ID, 15),
TITHE_FARM(WidgetID.TITHE_FARM_GROUP_ID, 3), TITHE_FARM(WidgetID.TITHE_FARM_GROUP_ID, 3),

View File

@@ -105,7 +105,7 @@ public class ArdougneDiaryRequirement extends GenericDiaryRequirement
add("Smith a Dragon sq shield in West Ardougne.", add("Smith a Dragon sq shield in West Ardougne.",
new SkillRequirement(Skill.SMITHING, 60), new SkillRequirement(Skill.SMITHING, 60),
new QuestRequirement(Quest.LEGENDS_QUEST)); new QuestRequirement(Quest.LEGENDS_QUEST));
add("Craft some Death runes.", add("Craft some Death runes from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 65), new SkillRequirement(Skill.RUNECRAFT, 65),
new QuestRequirement(Quest.MOURNINGS_END_PART_II)); new QuestRequirement(Quest.MOURNINGS_END_PART_II));

View File

@@ -84,7 +84,7 @@ public class FaladorDiaryRequirement extends GenericDiaryRequirement
new SkillRequirement(Skill.MAGIC, 37)); new SkillRequirement(Skill.MAGIC, 37));
// HARD // HARD
add("Craft 140 Mind runes simultaneously.", add("Craft 140 Mind runes simultaneously from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 56)); new SkillRequirement(Skill.RUNECRAFT, 56));
add("Change your family crest to the Saradomin symbol.", add("Change your family crest to the Saradomin symbol.",
new SkillRequirement(Skill.PRAYER, 70)); new SkillRequirement(Skill.PRAYER, 70));
@@ -106,7 +106,7 @@ public class FaladorDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.GRIM_TALES)); new QuestRequirement(Quest.GRIM_TALES));
// ELITE // ELITE
add("Craft 252 Air Runes simultaneously.", add("Craft 252 Air Runes simultaneously from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 88)); new SkillRequirement(Skill.RUNECRAFT, 88));
add("Purchase a White 2h Sword from Sir Vyvin.", add("Purchase a White 2h Sword from Sir Vyvin.",
new QuestRequirement(Quest.WANTED)); new QuestRequirement(Quest.WANTED));

View File

@@ -111,7 +111,7 @@ public class FremennikDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.THE_GIANT_DWARF, true)); new QuestRequirement(Quest.THE_GIANT_DWARF, true));
// ELITE // ELITE
add("Craft 56 astral runes at once.", add("Craft 56 astral runes at once from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 82), new SkillRequirement(Skill.RUNECRAFT, 82),
new QuestRequirement(Quest.LUNAR_DIPLOMACY)); new QuestRequirement(Quest.LUNAR_DIPLOMACY));
add("Create a dragonstone amulet in the Neitiznot furnace.", add("Create a dragonstone amulet in the Neitiznot furnace.",

View File

@@ -96,7 +96,7 @@ public class KaramjaDiaryRequirement extends GenericDiaryRequirement
); );
// HARD // HARD
add("Craft some nature runes.", add("Craft some nature runes from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 44), new SkillRequirement(Skill.RUNECRAFT, 44),
new QuestRequirement(Quest.RUNE_MYSTERIES)); new QuestRequirement(Quest.RUNE_MYSTERIES));
add("Cook a karambwan thoroughly.", add("Cook a karambwan thoroughly.",
@@ -122,7 +122,7 @@ public class KaramjaDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.SHILO_VILLAGE)); new QuestRequirement(Quest.SHILO_VILLAGE));
// ELITE // ELITE
add("Craft 56 Nature runes at once.", add("Craft 56 Nature runes at once from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 91)); new SkillRequirement(Skill.RUNECRAFT, 91));
add("Check the health of a palm tree in Brimhaven.", add("Check the health of a palm tree in Brimhaven.",
new SkillRequirement(Skill.FARMING, 68)); new SkillRequirement(Skill.FARMING, 68));

View File

@@ -110,7 +110,7 @@ public class KourendDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.DREAM_MENTOR)); new QuestRequirement(Quest.DREAM_MENTOR));
//ELITE //ELITE
add("Craft one or more Blood runes.", add("Craft one or more Blood runes from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 77), new SkillRequirement(Skill.RUNECRAFT, 77),
new SkillRequirement(Skill.MINING, 38), new SkillRequirement(Skill.MINING, 38),
new SkillRequirement(Skill.CRAFTING, 38), new SkillRequirement(Skill.CRAFTING, 38),

View File

@@ -43,7 +43,7 @@ public class LumbridgeDiaryRequirement extends GenericDiaryRequirement
new SkillRequirement(Skill.SLAYER, 7)); new SkillRequirement(Skill.SLAYER, 7));
add("Have Sedridor teleport you to the Essence Mine.", add("Have Sedridor teleport you to the Essence Mine.",
new QuestRequirement(Quest.RUNE_MYSTERIES)); new QuestRequirement(Quest.RUNE_MYSTERIES));
add("Craft some water runes.", add("Craft some water runes from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 5), new SkillRequirement(Skill.RUNECRAFT, 5),
new QuestRequirement(Quest.RUNE_MYSTERIES)); new QuestRequirement(Quest.RUNE_MYSTERIES));
add("Chop and burn some oak logs in Lumbridge.", add("Chop and burn some oak logs in Lumbridge.",
@@ -94,7 +94,7 @@ public class LumbridgeDiaryRequirement extends GenericDiaryRequirement
add("Squeeze past the jutting wall on your way to the cosmic altar.", add("Squeeze past the jutting wall on your way to the cosmic altar.",
new SkillRequirement(Skill.AGILITY, 46), new SkillRequirement(Skill.AGILITY, 46),
new QuestRequirement(Quest.LOST_CITY)); new QuestRequirement(Quest.LOST_CITY));
add("Craft 56 Cosmic runes simultaneously.", add("Craft 56 Cosmic runes simultaneously from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 59), new SkillRequirement(Skill.RUNECRAFT, 59),
new QuestRequirement(Quest.LOST_CITY)); new QuestRequirement(Quest.LOST_CITY));
add("Travel from Lumbridge to Edgeville on a Waka Canoe.", add("Travel from Lumbridge to Edgeville on a Waka Canoe.",
@@ -128,7 +128,7 @@ public class LumbridgeDiaryRequirement extends GenericDiaryRequirement
new SkillRequirement(Skill.WOODCUTTING, 75)); new SkillRequirement(Skill.WOODCUTTING, 75));
add("Smith an Adamant platebody down Draynor sewer.", add("Smith an Adamant platebody down Draynor sewer.",
new SkillRequirement(Skill.SMITHING, 88)); new SkillRequirement(Skill.SMITHING, 88));
add("Craft 140 or more Water runes at once.", add("Craft 140 or more Water runes at once from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 76), new SkillRequirement(Skill.RUNECRAFT, 76),
new QuestRequirement(Quest.RUNE_MYSTERIES)); new QuestRequirement(Quest.RUNE_MYSTERIES));
} }

View File

@@ -46,7 +46,7 @@ public class VarrockDiaryRequirement extends GenericDiaryRequirement
new SkillRequirement(Skill.AGILITY, 13)); new SkillRequirement(Skill.AGILITY, 13));
add("Spin a bowl on the pottery wheel and fire it in the oven in Barb Village.", add("Spin a bowl on the pottery wheel and fire it in the oven in Barb Village.",
new SkillRequirement(Skill.CRAFTING, 8)); new SkillRequirement(Skill.CRAFTING, 8));
add("Craft some Earth runes.", add("Craft some Earth runes from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 9)); new SkillRequirement(Skill.RUNECRAFT, 9));
add("Catch some trout in the River Lum at Barbarian Village.", add("Catch some trout in the River Lum at Barbarian Village.",
new SkillRequirement(Skill.FISHING, 20)); new SkillRequirement(Skill.FISHING, 20));
@@ -112,7 +112,7 @@ public class VarrockDiaryRequirement extends GenericDiaryRequirement
new SkillRequirement(Skill.SMITHING, 89), new SkillRequirement(Skill.SMITHING, 89),
new SkillRequirement(Skill.FLETCHING, 81), new SkillRequirement(Skill.FLETCHING, 81),
new QuestRequirement(Quest.THE_TOURIST_TRAP)); new QuestRequirement(Quest.THE_TOURIST_TRAP));
add("Craft 100 or more earth runes simultaneously.", add("Craft 100 or more earth runes simultaneously from Essence.",
new SkillRequirement(Skill.RUNECRAFT, 78), new SkillRequirement(Skill.RUNECRAFT, 78),
new QuestRequirement(Quest.RUNE_MYSTERIES)); new QuestRequirement(Quest.RUNE_MYSTERIES));
} }

View File

@@ -39,6 +39,7 @@ import net.runelite.api.GameObject;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.InventoryID; import net.runelite.api.InventoryID;
import net.runelite.api.Item; import net.runelite.api.Item;
import net.runelite.api.ItemContainer;
import net.runelite.api.ItemID; import net.runelite.api.ItemID;
import static net.runelite.api.ObjectID.CANNON_BASE; import static net.runelite.api.ObjectID.CANNON_BASE;
import net.runelite.api.Player; import net.runelite.api.Player;
@@ -301,6 +302,23 @@ public class CannonPlugin extends Plugin
cannonPlaced = true; cannonPlaced = true;
addCounter(); addCounter();
cballsLeft = 0; cballsLeft = 0;
final ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
if (inventory != null)
{
int invCballs = inventory.count(ItemID.GRANITE_CANNONBALL) > 0
? inventory.count(ItemID.GRANITE_CANNONBALL)
: inventory.count(ItemID.CANNONBALL);
// Cannonballs are always forcibly loaded after the furnace is added. If the player has more than
// the max number of cannon balls in their inventory, the cannon will always be fully filled.
// This is preferable to using the proceeding "You load the cannon with x cannon balls" message
// since it will show a lower number of cannon balls if the cannon is already partially-filled
// prior to being placed.
if (invCballs >= MAX_CBALLS)
{
cballsLeft = MAX_CBALLS;
}
}
} }
if (event.getMessage().contains("You pick up the cannon") if (event.getMessage().contains("You pick up the cannon")
@@ -366,6 +384,15 @@ public class CannonPlugin extends Plugin
} }
} }
if (event.getMessage().startsWith("Your cannon contains"))
{
Matcher m = NUMBER_PATTERN.matcher(event.getMessage());
if (m.find())
{
cballsLeft = Integer.parseInt(m.group());
}
}
if (event.getMessage().startsWith("You unload your cannon and receive Cannonball") if (event.getMessage().startsWith("You unload your cannon and receive Cannonball")
|| event.getMessage().startsWith("You unload your cannon and receive Granite cannonball")) || event.getMessage().startsWith("You unload your cannon and receive Granite cannonball"))
{ {

View File

@@ -1156,6 +1156,18 @@ public class ClueScrollPlugin extends Plugin
return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE; return mapClue.getObjectId() == -1 && itemId == ItemID.SPADE;
} }
else if (c instanceof SkillChallengeClue)
{
SkillChallengeClue challengeClue = (SkillChallengeClue) c;
for (ItemRequirement ir : challengeClue.getItemRequirements())
{
if (ir.fulfilledBy(itemId))
{
return true;
}
}
}
return false; return false;
} }

View File

@@ -179,7 +179,12 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam
any("", item(ItemID.GRACEFUL_GLOVES), item(ItemID.GRACEFUL_GLOVES_11859), item(ItemID.GRACEFUL_GLOVES_13587), item(ItemID.GRACEFUL_GLOVES_13588), item(ItemID.GRACEFUL_GLOVES_13599), item(ItemID.GRACEFUL_GLOVES_13600), item(ItemID.GRACEFUL_GLOVES_13611), item(ItemID.GRACEFUL_GLOVES_13612), item(ItemID.GRACEFUL_GLOVES_13623), item(ItemID.GRACEFUL_GLOVES_13624), item(ItemID.GRACEFUL_GLOVES_13635), item(ItemID.GRACEFUL_GLOVES_13636), item(ItemID.GRACEFUL_GLOVES_13675), item(ItemID.GRACEFUL_GLOVES_13676), item(ItemID.GRACEFUL_GLOVES_21073), item(ItemID.GRACEFUL_GLOVES_21075), item(ItemID.GRACEFUL_GLOVES_24755), item(ItemID.GRACEFUL_GLOVES_24757), item(ItemID.GRACEFUL_GLOVES_25081), item(ItemID.GRACEFUL_GLOVES_25083)), any("", item(ItemID.GRACEFUL_GLOVES), item(ItemID.GRACEFUL_GLOVES_11859), item(ItemID.GRACEFUL_GLOVES_13587), item(ItemID.GRACEFUL_GLOVES_13588), item(ItemID.GRACEFUL_GLOVES_13599), item(ItemID.GRACEFUL_GLOVES_13600), item(ItemID.GRACEFUL_GLOVES_13611), item(ItemID.GRACEFUL_GLOVES_13612), item(ItemID.GRACEFUL_GLOVES_13623), item(ItemID.GRACEFUL_GLOVES_13624), item(ItemID.GRACEFUL_GLOVES_13635), item(ItemID.GRACEFUL_GLOVES_13636), item(ItemID.GRACEFUL_GLOVES_13675), item(ItemID.GRACEFUL_GLOVES_13676), item(ItemID.GRACEFUL_GLOVES_21073), item(ItemID.GRACEFUL_GLOVES_21075), item(ItemID.GRACEFUL_GLOVES_24755), item(ItemID.GRACEFUL_GLOVES_24757), item(ItemID.GRACEFUL_GLOVES_25081), item(ItemID.GRACEFUL_GLOVES_25083)),
any("", item(ItemID.GRACEFUL_BOOTS), item(ItemID.GRACEFUL_BOOTS_11861), item(ItemID.GRACEFUL_BOOTS_13589), item(ItemID.GRACEFUL_BOOTS_13590), item(ItemID.GRACEFUL_BOOTS_13601), item(ItemID.GRACEFUL_BOOTS_13602), item(ItemID.GRACEFUL_BOOTS_13613), item(ItemID.GRACEFUL_BOOTS_13614), item(ItemID.GRACEFUL_BOOTS_13625), item(ItemID.GRACEFUL_BOOTS_13626), item(ItemID.GRACEFUL_BOOTS_13637), item(ItemID.GRACEFUL_BOOTS_13638), item(ItemID.GRACEFUL_BOOTS_13677), item(ItemID.GRACEFUL_BOOTS_13678), item(ItemID.GRACEFUL_BOOTS_21076), item(ItemID.GRACEFUL_BOOTS_21078), item(ItemID.GRACEFUL_BOOTS_24758), item(ItemID.GRACEFUL_BOOTS_24760), item(ItemID.GRACEFUL_BOOTS_25084), item(ItemID.GRACEFUL_BOOTS_25086)))), any("", item(ItemID.GRACEFUL_BOOTS), item(ItemID.GRACEFUL_BOOTS_11861), item(ItemID.GRACEFUL_BOOTS_13589), item(ItemID.GRACEFUL_BOOTS_13590), item(ItemID.GRACEFUL_BOOTS_13601), item(ItemID.GRACEFUL_BOOTS_13602), item(ItemID.GRACEFUL_BOOTS_13613), item(ItemID.GRACEFUL_BOOTS_13614), item(ItemID.GRACEFUL_BOOTS_13625), item(ItemID.GRACEFUL_BOOTS_13626), item(ItemID.GRACEFUL_BOOTS_13637), item(ItemID.GRACEFUL_BOOTS_13638), item(ItemID.GRACEFUL_BOOTS_13677), item(ItemID.GRACEFUL_BOOTS_13678), item(ItemID.GRACEFUL_BOOTS_21076), item(ItemID.GRACEFUL_BOOTS_21078), item(ItemID.GRACEFUL_BOOTS_24758), item(ItemID.GRACEFUL_BOOTS_24760), item(ItemID.GRACEFUL_BOOTS_25084), item(ItemID.GRACEFUL_BOOTS_25086)))),
new SkillChallengeClue("Mix an anti-venom potion.", item(ItemID.ANTIDOTE4_5952), xOfItem(ItemID.ZULRAHS_SCALES, 20)), new SkillChallengeClue("Mix an anti-venom potion.", item(ItemID.ANTIDOTE4_5952), xOfItem(ItemID.ZULRAHS_SCALES, 20)),
new SkillChallengeClue("Mine a piece of Runite ore", "mine a piece of runite ore whilst sporting the finest mining gear.", true, ANY_PICKAXE, all("Prospector kit", item(ItemID.PROSPECTOR_HELMET), any("", item(ItemID.PROSPECTOR_JACKET), item(ItemID.VARROCK_ARMOUR_4)), item(ItemID.PROSPECTOR_LEGS), item(ItemID.PROSPECTOR_BOOTS))), new SkillChallengeClue("Mine a piece of Runite ore", "mine a piece of runite ore whilst sporting the finest mining gear.", true, ANY_PICKAXE,
all("Prospector kit",
any("", item(ItemID.PROSPECTOR_HELMET), item(ItemID.GOLDEN_PROSPECTOR_HELMET)),
any("", item(ItemID.PROSPECTOR_JACKET), item(ItemID.VARROCK_ARMOUR_4), item(ItemID.GOLDEN_PROSPECTOR_JACKET)),
any("", item(ItemID.PROSPECTOR_LEGS), item(ItemID.GOLDEN_PROSPECTOR_LEGS)),
any("", item(ItemID.PROSPECTOR_BOOTS), item(ItemID.GOLDEN_PROSPECTOR_BOOTS)))),
new SkillChallengeClue("Steal a gem from the Ardougne market."), new SkillChallengeClue("Steal a gem from the Ardougne market."),
new SkillChallengeClue("Pickpocket an elf."), new SkillChallengeClue("Pickpocket an elf."),
new SkillChallengeClue("Bind a blood rune at the blood altar.", item(ItemID.DARK_ESSENCE_FRAGMENTS)), new SkillChallengeClue("Bind a blood rune at the blood altar.", item(ItemID.DARK_ESSENCE_FRAGMENTS)),
@@ -188,7 +193,12 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam
new SkillChallengeClue("Cremate a set of fiyr remains.", any("Magic or Redwood Pyre Logs", item(ItemID.MAGIC_PYRE_LOGS), item(ItemID.REDWOOD_PYRE_LOGS)), item(ItemID.TINDERBOX), item(ItemID.FIYR_REMAINS)), new SkillChallengeClue("Cremate a set of fiyr remains.", any("Magic or Redwood Pyre Logs", item(ItemID.MAGIC_PYRE_LOGS), item(ItemID.REDWOOD_PYRE_LOGS)), item(ItemID.TINDERBOX), item(ItemID.FIYR_REMAINS)),
new SkillChallengeClue("Dissect a sacred eel.", item(ItemID.KNIFE), any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.FISHING_BAIT)), new SkillChallengeClue("Dissect a sacred eel.", item(ItemID.KNIFE), any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.FISHING_BAIT)),
new SkillChallengeClue("Kill a lizardman shaman."), new SkillChallengeClue("Kill a lizardman shaman."),
new SkillChallengeClue("Catch an Anglerfish.", "angle for an anglerfish whilst sporting the finest fishing gear.", true, any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.SANDWORMS), all("Angler's outfit", item(ItemID.ANGLER_HAT), item(ItemID.ANGLER_TOP), item(ItemID.ANGLER_WADERS), item(ItemID.ANGLER_BOOTS))), new SkillChallengeClue("Catch an Anglerfish.", "angle for an anglerfish whilst sporting the finest fishing gear.", true, any("Fishing rod", item(ItemID.FISHING_ROD), item(ItemID.PEARL_FISHING_ROD)), item(ItemID.SANDWORMS),
all("Angler's outfit",
any("", item(ItemID.ANGLER_HAT), item(ItemID.SPIRIT_ANGLER_HEADBAND)),
any("", item(ItemID.ANGLER_TOP), item(ItemID.SPIRIT_ANGLER_TOP)),
any("", item(ItemID.ANGLER_WADERS), item(ItemID.SPIRIT_ANGLER_WADERS)),
any("", item(ItemID.ANGLER_BOOTS), item(ItemID.SPIRIT_ANGLER_BOOTS)))),
new SkillChallengeClue("Chop a redwood log.", "chop a redwood log whilst sporting the finest lumberjack gear.", true, ANY_AXE, all("Lumberjack outfit", item(ItemID.LUMBERJACK_HAT), item(ItemID.LUMBERJACK_TOP), item(ItemID.LUMBERJACK_LEGS), item(ItemID.LUMBERJACK_BOOTS))), new SkillChallengeClue("Chop a redwood log.", "chop a redwood log whilst sporting the finest lumberjack gear.", true, ANY_AXE, all("Lumberjack outfit", item(ItemID.LUMBERJACK_HAT), item(ItemID.LUMBERJACK_TOP), item(ItemID.LUMBERJACK_LEGS), item(ItemID.LUMBERJACK_BOOTS))),
new SkillChallengeClue("Craft a light orb in the Dorgesh-Kaan bank.", item(ItemID.CAVE_GOBLIN_WIRE), item(ItemID.EMPTY_LIGHT_ORB)), new SkillChallengeClue("Craft a light orb in the Dorgesh-Kaan bank.", item(ItemID.CAVE_GOBLIN_WIRE), item(ItemID.EMPTY_LIGHT_ORB)),
new SkillChallengeClue("Kill a reanimated Abyssal Demon.", "kill a reanimated abyssal.", xOfItem(ItemID.SOUL_RUNE, 4), xOfItem(ItemID.BLOOD_RUNE, 1), any("Nature Rune x4", xOfItem(ItemID.NATURE_RUNE, 4), item(ItemID.BRYOPHYTAS_STAFF)), range("Ensouled abyssal head", ItemID.ENSOULED_ABYSSAL_HEAD, ItemID.ENSOULED_ABYSSAL_HEAD_13508)), new SkillChallengeClue("Kill a reanimated Abyssal Demon.", "kill a reanimated abyssal.", xOfItem(ItemID.SOUL_RUNE, 4), xOfItem(ItemID.BLOOD_RUNE, 1), any("Nature Rune x4", xOfItem(ItemID.NATURE_RUNE, 4), item(ItemID.BRYOPHYTAS_STAFF)), range("Ensouled abyssal head", ItemID.ENSOULED_ABYSSAL_HEAD, ItemID.ENSOULED_ABYSSAL_HEAD_13508)),

View File

@@ -173,22 +173,22 @@ public interface FishingConfig extends Config
@ConfigItem( @ConfigItem(
position = 11, position = 11,
keyName = "trawlerNotification", keyName = "trawlerTimer",
name = "Trawler activity notification", name = "Trawler timer in M:SS",
description = "Send a notification when fishing trawler activity drops below 15%." description = "Trawler timer will display a more accurate timer in M:SS format."
) )
default boolean trawlerNotification() default boolean trawlerTimer()
{ {
return true; return true;
} }
@ConfigItem( @ConfigItem(
position = 12, position = 12,
keyName = "trawlerTimer", keyName = "trawlerContribution",
name = "Trawler timer in MM:SS", name = "Trawler contribution",
description = "Trawler Timer will display a more accurate timer in MM:SS format." description = "Display the exact number of trawler contribution points gained."
) )
default boolean trawlerTimer() default boolean trawlerContribution()
{ {
return true; return true;
} }

View File

@@ -57,7 +57,6 @@ import net.runelite.api.events.InteractingChanged;
import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.NpcSpawned;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded; import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetID;
@@ -86,8 +85,7 @@ public class FishingPlugin extends Plugin
{ {
private static final int TRAWLER_SHIP_REGION_NORMAL = 7499; private static final int TRAWLER_SHIP_REGION_NORMAL = 7499;
private static final int TRAWLER_SHIP_REGION_SINKING = 8011; private static final int TRAWLER_SHIP_REGION_SINKING = 8011;
private static final int TRAWLER_TIME_LIMIT_IN_SECONDS = 614; private static final int TRAWLER_TIME_LIMIT_IN_SECONDS = 314;
private static final int TRAWLER_ACTIVITY_THRESHOLD = Math.round(0.15f * 255);
private Instant trawlerStartTime; private Instant trawlerStartTime;
@@ -124,8 +122,6 @@ public class FishingPlugin extends Plugin
@Inject @Inject
private FishingSpotMinimapOverlay fishingSpotMinimapOverlay; private FishingSpotMinimapOverlay fishingSpotMinimapOverlay;
private boolean trawlerNotificationSent;
@Provides @Provides
FishingConfig provideConfig(ConfigManager configManager) FishingConfig provideConfig(ConfigManager configManager)
{ {
@@ -150,7 +146,6 @@ public class FishingPlugin extends Plugin
overlayManager.remove(fishingSpotMinimapOverlay); overlayManager.remove(fishingSpotMinimapOverlay);
fishingSpots.clear(); fishingSpots.clear();
minnowSpots.clear(); minnowSpots.clear();
trawlerNotificationSent = false;
currentSpot = null; currentSpot = null;
trawlerStartTime = null; trawlerStartTime = null;
} }
@@ -328,10 +323,8 @@ public class FishingPlugin extends Plugin
} }
} }
if (config.trawlerTimer()) updateTrawlerTimer();
{ updateTrawlerContribution();
updateTrawlerTimer();
}
} }
@Subscribe @Subscribe
@@ -362,40 +355,42 @@ public class FishingPlugin extends Plugin
} }
} }
@Subscribe
public void onVarbitChanged(VarbitChanged event)
{
if (!config.trawlerNotification() || client.getGameState() != GameState.LOGGED_IN)
{
return;
}
int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
if ((regionID == TRAWLER_SHIP_REGION_NORMAL || regionID == TRAWLER_SHIP_REGION_SINKING)
&& client.getVar(Varbits.FISHING_TRAWLER_ACTIVITY) <= TRAWLER_ACTIVITY_THRESHOLD)
{
if (!trawlerNotificationSent)
{
notifier.notify("You have low Fishing Trawler activity!");
trawlerNotificationSent = true;
}
}
else
{
trawlerNotificationSent = false;
}
}
@Subscribe @Subscribe
public void onWidgetLoaded(WidgetLoaded event) public void onWidgetLoaded(WidgetLoaded event)
{ {
if (event.getGroupId() == WidgetID.FISHING_TRAWLER_GROUP_ID) if (event.getGroupId() == WidgetID.FISHING_TRAWLER_GROUP_ID)
{ {
trawlerStartTime = Instant.now(); trawlerStartTime = Instant.now();
log.debug("Trawler session started");
} }
} }
/**
* Updates the trawler contribution value
*/
private void updateTrawlerContribution()
{
int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
if (regionID != TRAWLER_SHIP_REGION_NORMAL && regionID != TRAWLER_SHIP_REGION_SINKING)
{
return;
}
if (!config.trawlerContribution())
{
return;
}
Widget trawlerContributionWidget = client.getWidget(WidgetInfo.FISHING_TRAWLER_CONTRIBUTION);
if (trawlerContributionWidget == null)
{
return;
}
int trawlerContribution = client.getVar(Varbits.FISHING_TRAWLER_ACTIVITY);
trawlerContributionWidget.setText("Contribution: " + trawlerContribution);
}
/** /**
* Changes the Fishing Trawler timer widget from minutes to minutes and seconds * Changes the Fishing Trawler timer widget from minutes to minutes and seconds
*/ */
@@ -414,6 +409,11 @@ public class FishingPlugin extends Plugin
return; return;
} }
if (!config.trawlerTimer())
{
return;
}
Widget trawlerTimerWidget = client.getWidget(WidgetInfo.FISHING_TRAWLER_TIMER); Widget trawlerTimerWidget = client.getWidget(WidgetInfo.FISHING_TRAWLER_TIMER);
if (trawlerTimerWidget == null) if (trawlerTimerWidget == null)
{ {
@@ -438,7 +438,7 @@ public class FishingPlugin extends Plugin
} }
else else
{ {
trawlerText.append("00"); trawlerText.append('0');
} }
trawlerText.append(':'); trawlerText.append(':');

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2021, Maciej <https://github.com/mlewicki12>
* 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.friendlist;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("friendlist")
public interface FriendListConfig extends Config
{
@ConfigItem(
keyName = "showWorldOnLogin",
name = "Show world on login",
description = "Shows world number on friend login notifications"
)
default boolean showWorldOnLogin()
{
return false;
}
}

View File

@@ -25,19 +25,26 @@
*/ */
package net.runelite.client.plugins.friendlist; package net.runelite.client.plugins.friendlist;
import com.google.inject.Provides;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.ChatPlayer;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Friend; import net.runelite.api.Friend;
import net.runelite.api.Ignore; import net.runelite.api.Ignore;
import net.runelite.api.MessageNode;
import net.runelite.api.NameableContainer; import net.runelite.api.NameableContainer;
import net.runelite.api.ScriptID; import net.runelite.api.ScriptID;
import net.runelite.api.VarPlayer; import net.runelite.api.VarPlayer;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ScriptPostFired; import net.runelite.api.events.ScriptPostFired;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.Text;
@PluginDescriptor( @PluginDescriptor(
name = "Friend List", name = "Friend List",
@@ -54,6 +61,15 @@ public class FriendListPlugin extends Plugin
@Inject @Inject
private Client client; private Client client;
@Inject
private FriendListConfig config;
@Provides
FriendListConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(FriendListConfig.class);
}
@Override @Override
protected void shutDown() protected void shutDown()
{ {
@@ -109,6 +125,25 @@ public class FriendListPlugin extends Plugin
} }
} }
@Subscribe
public void onChatMessage(ChatMessage message)
{
if (message.getType() == ChatMessageType.LOGINLOGOUTNOTIFICATION && config.showWorldOnLogin())
{
MessageNode messageNode = message.getMessageNode();
// get the player name out of the notification
String name = messageNode.getValue()
.substring(0, messageNode.getValue().indexOf(" "));
ChatPlayer player = findFriend(name);
if (player != null && player.getWorld() > 0)
{
messageNode
.setValue(messageNode.getValue() + String.format(" (World %d)", player.getWorld()));
}
}
}
private void setFriendsListTitle(final String title) private void setFriendsListTitle(final String title)
{ {
Widget friendListTitleWidget = client.getWidget(WidgetInfo.FRIEND_CHAT_TITLE); Widget friendListTitleWidget = client.getWidget(WidgetInfo.FRIEND_CHAT_TITLE);
@@ -126,4 +161,16 @@ public class FriendListPlugin extends Plugin
ignoreTitleWidget.setText(title); ignoreTitleWidget.setText(title);
} }
} }
private ChatPlayer findFriend(String name)
{
NameableContainer<Friend> friendContainer = client.getFriendContainer();
if (friendContainer != null)
{
String cleanName = Text.removeTags(name);
return friendContainer.findByName(cleanName);
}
return null;
}
} }

View File

@@ -189,6 +189,7 @@ public class IdleNotifierPlugin extends Plugin
case FLETCHING_ATTACH_BOLT_TIPS_TO_DRAGON_BOLT: case FLETCHING_ATTACH_BOLT_TIPS_TO_DRAGON_BOLT:
/* Smithing(Anvil, Furnace, Cannonballs */ /* Smithing(Anvil, Furnace, Cannonballs */
case SMITHING_ANVIL: case SMITHING_ANVIL:
case SMITHING_IMCANDO_HAMMER:
case SMITHING_SMELTING: case SMITHING_SMELTING:
case SMITHING_CANNONBALL: case SMITHING_CANNONBALL:
/* Fishing */ /* Fishing */

View File

@@ -34,6 +34,7 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import static net.runelite.api.AnimationID.CONSTRUCTION; import static net.runelite.api.AnimationID.CONSTRUCTION;
import static net.runelite.api.AnimationID.CONSTRUCTION_IMCANDO;
import static net.runelite.api.AnimationID.FIREMAKING; import static net.runelite.api.AnimationID.FIREMAKING;
import static net.runelite.api.AnimationID.FLETCHING_BOW_CUTTING; import static net.runelite.api.AnimationID.FLETCHING_BOW_CUTTING;
import static net.runelite.api.AnimationID.IDLE; import static net.runelite.api.AnimationID.IDLE;
@@ -436,6 +437,7 @@ public class WintertodtPlugin extends Plugin
break; break;
case CONSTRUCTION: case CONSTRUCTION:
case CONSTRUCTION_IMCANDO:
setActivity(WintertodtActivity.FIXING_BRAZIER); setActivity(WintertodtActivity.FIXING_BRAZIER);
break; break;
} }

View File

@@ -136,6 +136,17 @@ public interface WorldHopperConfig extends Config
return SubscriptionFilterMode.BOTH; return SubscriptionFilterMode.BOTH;
} }
@ConfigItem(
keyName = "regionFilter",
name = "Filter worlds by region",
description = "Restrict sidebar worlds to one region",
position = 8
)
default RegionFilterMode regionFilter()
{
return RegionFilterMode.NONE;
}
@ConfigItem( @ConfigItem(
keyName = "displayPing", keyName = "displayPing",
name = "Display current ping", name = "Display current ping",

View File

@@ -209,7 +209,8 @@ public class WorldHopperPlugin extends Plugin
overlayManager.add(worldHopperOverlay); overlayManager.add(worldHopperOverlay);
panel.setFilterMode(config.subscriptionFilter()); panel.setSubscriptionFilterMode(config.subscriptionFilter());
panel.setRegionFilterMode(config.regionFilter());
// The plugin has its own executor for pings, as it blocks for a long time // The plugin has its own executor for pings, as it blocks for a long time
hopperExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()); hopperExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor());
@@ -272,7 +273,11 @@ public class WorldHopperPlugin extends Plugin
} }
break; break;
case "subscriptionFilter": case "subscriptionFilter":
panel.setFilterMode(config.subscriptionFilter()); panel.setSubscriptionFilterMode(config.subscriptionFilter());
updateList();
break;
case "regionFilter":
panel.setRegionFilterMode(config.regionFilter());
updateList(); updateList();
break; break;
} }

View File

@@ -66,7 +66,9 @@ class WorldSwitcherPanel extends PluginPanel
private final ArrayList<WorldTableRow> rows = new ArrayList<>(); private final ArrayList<WorldTableRow> rows = new ArrayList<>();
private final WorldHopperPlugin plugin; private final WorldHopperPlugin plugin;
@Setter(AccessLevel.PACKAGE) @Setter(AccessLevel.PACKAGE)
private SubscriptionFilterMode filterMode; private SubscriptionFilterMode subscriptionFilterMode;
@Setter(AccessLevel.PACKAGE)
private RegionFilterMode regionFilterMode;
WorldSwitcherPanel(WorldHopperPlugin plugin) WorldSwitcherPanel(WorldHopperPlugin plugin)
{ {
@@ -231,7 +233,7 @@ class WorldSwitcherPanel extends PluginPanel
{ {
World world = worlds.get(i); World world = worlds.get(i);
switch (filterMode) switch (subscriptionFilterMode)
{ {
case FREE: case FREE:
if (world.getTypes().contains(WorldType.MEMBERS)) if (world.getTypes().contains(WorldType.MEMBERS))
@@ -247,6 +249,11 @@ class WorldSwitcherPanel extends PluginPanel
break; break;
} }
if (regionFilterMode.getRegion() != null && !regionFilterMode.getRegion().equals(world.getRegion()))
{
continue;
}
rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world))); rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld() && plugin.getLastWorld() != 0, plugin.isFavorite(world)));
} }

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2021, Alexsuperfly <alexsuperfly@users.noreply.github.com>
* Copyright (c) 2021, Jordan Atwood <nightfirecat@protonmail.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.cannon;
import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind;
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.InventoryID;
import net.runelite.api.ItemContainer;
import net.runelite.api.ItemID;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.Notifier;
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.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class CannonPluginTest
{
@Inject
private CannonPlugin plugin;
@Mock
@Bind
private CannonConfig config;
@Mock
@Bind
private CannonOverlay cannonOverlay;
@Mock
@Bind
private CannonSpotOverlay cannonSpotOverlay;
@Mock
@Bind
private InfoBoxManager infoBoxManager;
@Mock
@Bind
private Notifier notifier;
@Mock
@Bind
private ItemManager itemManager;
@Mock
@Bind
private Client client;
@Mock
@Bind
private OverlayManager overlayManager;
private static final ChatMessage ADD_FURNACE = new ChatMessage();
@BeforeClass
public static void chatMessageSetup()
{
ADD_FURNACE.setType(ChatMessageType.SPAM);
ADD_FURNACE.setMessage("You add the furnace.");
}
@Before
public void before()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
@Test
public void addWrongTypeOfCannonballs()
{
final ChatMessage message = new ChatMessage();
message.setType(ChatMessageType.GAMEMESSAGE);
message.setMessage("Your cannon contains 20 x Cannonball.<br>You can only add cannonballs of the same kind.");
plugin.onChatMessage(message);
assertEquals(20, plugin.getCballsLeft());
}
@Test
public void addMaxCannonballs()
{
final ItemContainer inventory = mock(ItemContainer.class);
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory);
when(inventory.count(ItemID.CANNONBALL)).thenReturn(100);
when(inventory.count(ItemID.GRANITE_CANNONBALL)).thenReturn(0);
plugin.onChatMessage(ADD_FURNACE);
assertTrue(plugin.isCannonPlaced());
assertEquals(30, plugin.getCballsLeft());
plugin.onChatMessage(loadCannonballs(30));
assertEquals(30, plugin.getCballsLeft());
}
@Test
public void addNotMaxCannonballs()
{
final ItemContainer inventory = mock(ItemContainer.class);
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory);
when(inventory.count(ItemID.GRANITE_CANNONBALL)).thenReturn(12);
plugin.onChatMessage(ADD_FURNACE);
assertTrue(plugin.isCannonPlaced());
assertEquals(0, plugin.getCballsLeft());
plugin.onChatMessage(loadCannonballs(12));
assertEquals(12, plugin.getCballsLeft());
}
@Test
public void addReclaimedCannonballs()
{
final ItemContainer inventory = mock(ItemContainer.class);
when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inventory);
when(inventory.count(ItemID.CANNONBALL)).thenReturn(1250);
plugin.onChatMessage(ADD_FURNACE);
assertTrue(plugin.isCannonPlaced());
assertEquals(30, plugin.getCballsLeft());
plugin.onChatMessage(loadCannonballs(18));
assertEquals(30, plugin.getCballsLeft());
}
private static ChatMessage loadCannonballs(final int numCannonballs)
{
final ChatMessage message = new ChatMessage();
message.setType(ChatMessageType.GAMEMESSAGE);
// Cannons use the same chat message for loading cannonballs regardless of whether they're normal or granite.
if (numCannonballs == 1)
{
message.setMessage("You load the cannon with one cannonball.");
}
else
{
message.setMessage(String.format("You load the cannon with %s cannonballs.", numCannonballs));
}
return message;
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2021, Maciej <https://github.com/mlewicki12>
* 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.friendlist;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.Friend;
import net.runelite.api.MessageNode;
import net.runelite.api.NameableContainer;
import net.runelite.api.events.ChatMessage;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class FriendListPluginTest
{
@Mock
@Bind
private Client client;
@Mock
@Bind
private FriendListConfig config;
@Inject
private FriendListPlugin friendListPlugin;
@Before
public void before()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
@Test
public void onChatMessage()
{
when(config.showWorldOnLogin()).thenReturn(true);
MessageNode messageNode = mock(MessageNode.class);
when(messageNode.getValue()).thenReturn("test\u00a0rsn has logged in.");
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType(ChatMessageType.LOGINLOGOUTNOTIFICATION);
chatMessage.setMessageNode(messageNode);
Friend friend = mock(Friend.class);
when(friend.getWorld()).thenReturn(311);
NameableContainer<Friend> friendContainer = mock(NameableContainer.class);
when(friendContainer.findByName("test\u00a0rsn")).thenReturn(friend);
when(client.getFriendContainer()).thenReturn(friendContainer);
friendListPlugin.onChatMessage(chatMessage);
verify(messageNode).setValue("test\u00a0rsn has logged in. (World 311)");
}
}

View File

@@ -1406,4 +1406,10 @@ public interface RSClient extends RSGameEngine, Client
@Construct @Construct
RSSceneTilePaint createSceneTilePaint(int swColor, int seColor, int neColor, int nwColor, int texture, int rgb, boolean isFlat); RSSceneTilePaint createSceneTilePaint(int swColor, int seColor, int neColor, int nwColor, int texture, int rgb, boolean isFlat);
@Import("crossWorldMessageIds")
long[] getCrossWorldMessageIds();
@Import("crossWorldMessageIdsIndex")
int getCrossWorldMessageIdsIndex();
} }

View File

@@ -9,7 +9,7 @@ public interface RSPlayerComposition extends PlayerComposition
boolean isFemale(); boolean isFemale();
@Import("bodyColors") @Import("bodyColors")
int[] getBodyPartColours(); int[] getColors();
@Import("hash") @Import("hash")
long getHash(); long getHash();

View File

@@ -180,7 +180,8 @@ public final class Client extends GameEngine implements Usernamed {
@Export("minimapState") @Export("minimapState")
static int minimapState; static int minimapState;
@ObfuscatedName("pt") @ObfuscatedName("pt")
static long[] field689; @Export("crossWorldMessageIds")
static long[] crossWorldMessageIds;
@ObfuscatedName("qt") @ObfuscatedName("qt")
@ObfuscatedGetter( @ObfuscatedGetter(
intValue = -163319865 intValue = -163319865
@@ -195,7 +196,8 @@ public final class Client extends GameEngine implements Usernamed {
@ObfuscatedGetter( @ObfuscatedGetter(
intValue = 1846796199 intValue = 1846796199
) )
static int field760; @Export("crossWorldMessageIdsIndex")
static int crossWorldMessageIdsIndex;
@ObfuscatedName("st") @ObfuscatedName("st")
@ObfuscatedSignature( @ObfuscatedSignature(
descriptor = "Lmi;" descriptor = "Lmi;"
@@ -1534,8 +1536,8 @@ public final class Client extends GameEngine implements Usernamed {
publicChatMode = 0; // L: 573 publicChatMode = 0; // L: 573
tradeChatMode = 0; // L: 575 tradeChatMode = 0; // L: 575
field824 = ""; // L: 576 field824 = ""; // L: 576
field689 = new long[100]; // L: 578 crossWorldMessageIds = new long[100]; // L: 578
field760 = 0; // L: 579 crossWorldMessageIdsIndex = 0; // L: 579
field827 = 0; // L: 581 field827 = 0; // L: 581
field828 = new int[128]; // L: 582 field828 = new int[128]; // L: 582
field792 = new int[128]; // L: 583 field792 = new int[128]; // L: 583
@@ -3836,7 +3838,7 @@ public final class Client extends GameEngine implements Usernamed {
boolean var12 = false; // L: 5460 boolean var12 = false; // L: 5460
for (var53 = 0; var53 < 100; ++var53) { // L: 5461 for (var53 = 0; var53 < 100; ++var53) { // L: 5461
if (field689[var53] == var10) { // L: 5462 if (crossWorldMessageIds[var53] == var10) { // L: 5462
var12 = true; // L: 5463 var12 = true; // L: 5463
break; // L: 5464 break; // L: 5464
} }
@@ -3847,8 +3849,8 @@ public final class Client extends GameEngine implements Usernamed {
} }
if (!var12 && field716 == 0) { // L: 5468 if (!var12 && field716 == 0) { // L: 5468
field689[field760] = var10; // L: 5469 crossWorldMessageIds[crossWorldMessageIdsIndex] = var10; // L: 5469
field760 = (field760 + 1) % 100; // L: 5470 crossWorldMessageIdsIndex = (crossWorldMessageIdsIndex + 1) % 100; // L: 5470
var22 = AbstractFont.escapeBrackets(GrandExchangeOfferAgeComparator.method4607(class16.method258(var3))); // L: 5471 var22 = AbstractFont.escapeBrackets(GrandExchangeOfferAgeComparator.method4607(class16.method258(var3))); // L: 5471
byte var55; byte var55;
if (var9.isPrivileged) { // L: 5473 if (var9.isPrivileged) { // L: 5473
@@ -4379,7 +4381,7 @@ public final class Client extends GameEngine implements Usernamed {
var11 = true; var11 = true;
} else { } else {
for (var53 = 0; var53 < 100; ++var53) { // L: 5866 for (var53 = 0; var53 < 100; ++var53) { // L: 5866
if (field689[var53] == var31) { // L: 5867 if (crossWorldMessageIds[var53] == var31) { // L: 5867
var11 = true; // L: 5868 var11 = true; // L: 5868
break; // L: 5869 break; // L: 5869
} }
@@ -4387,8 +4389,8 @@ public final class Client extends GameEngine implements Usernamed {
} }
if (!var11) { // L: 5873 if (!var11) { // L: 5873
field689[field760] = var31; // L: 5874 crossWorldMessageIds[crossWorldMessageIdsIndex] = var31; // L: 5874
field760 = (field760 + 1) % 100; // L: 5875 crossWorldMessageIdsIndex = (crossWorldMessageIdsIndex + 1) % 100; // L: 5875
var22 = class16.method258(var3); // L: 5876 var22 = class16.method258(var3); // L: 5876
int var54 = var56 >= 0 ? 43 : 46; // L: 5877 int var54 = var56 >= 0 ? 43 : 46; // L: 5877
Projectile.addChatMessage(var54, "", var22, var33.field25); // L: 5878 Projectile.addChatMessage(var54, "", var22, var33.field25); // L: 5878
@@ -4659,7 +4661,7 @@ public final class Client extends GameEngine implements Usernamed {
break; break;
} }
if (var39 == field689[var15]) { // L: 6076 if (var39 == crossWorldMessageIds[var15]) { // L: 6076
var13 = true; // L: 6077 var13 = true; // L: 6077
break; // L: 6078 break; // L: 6078
} }
@@ -4669,8 +4671,8 @@ public final class Client extends GameEngine implements Usernamed {
} }
if (!var13) { // L: 6085 if (!var13) { // L: 6085
field689[field760] = var39; // L: 6086 crossWorldMessageIds[crossWorldMessageIdsIndex] = var39; // L: 6086
field760 = (field760 + 1) % 100; // L: 6087 crossWorldMessageIdsIndex = (crossWorldMessageIdsIndex + 1) % 100; // L: 6087
var42 = AbstractFont.escapeBrackets(class16.method258(var3)); // L: 6088 var42 = AbstractFont.escapeBrackets(class16.method258(var3)); // L: 6088
int var16 = var56 >= 0 ? 41 : 44; // L: 6089 int var16 = var56 >= 0 ? 41 : 44; // L: 6089
if (var74.modIcon != -1) { // L: 6090 if (var74.modIcon != -1) { // L: 6090
@@ -5017,7 +5019,7 @@ public final class Client extends GameEngine implements Usernamed {
boolean var14 = false; // L: 6349 boolean var14 = false; // L: 6349
for (var15 = 0; var15 < 100; ++var15) { // L: 6350 for (var15 = 0; var15 < 100; ++var15) { // L: 6350
if (var29 == field689[var15]) { // L: 6351 if (var29 == crossWorldMessageIds[var15]) { // L: 6351
var14 = true; // L: 6352 var14 = true; // L: 6352
break; // L: 6353 break; // L: 6353
} }
@@ -5028,8 +5030,8 @@ public final class Client extends GameEngine implements Usernamed {
} }
if (!var14 && field716 == 0) { // L: 6359 if (!var14 && field716 == 0) { // L: 6359
field689[field760] = var29; // L: 6360 crossWorldMessageIds[crossWorldMessageIdsIndex] = var29; // L: 6360
field760 = (field760 + 1) % 100; // L: 6361 crossWorldMessageIdsIndex = (crossWorldMessageIdsIndex + 1) % 100; // L: 6361
var42 = AbstractFont.escapeBrackets(GrandExchangeOfferAgeComparator.method4607(class16.method258(var3))); // L: 6362 var42 = AbstractFont.escapeBrackets(GrandExchangeOfferAgeComparator.method4607(class16.method258(var3))); // L: 6362
if (var34.modIcon != -1) { // L: 6363 if (var34.modIcon != -1) { // L: 6363
Projectile.addChatMessage(9, class337.method5986(var34.modIcon) + var45, var42, Varcs.base37DecodeLong(var20)); Projectile.addChatMessage(9, class337.method5986(var34.modIcon) + var45, var42, Varcs.base37DecodeLong(var20));