Merge remote-tracking branch 'runelite/master'
This commit is contained in:
@@ -29,6 +29,7 @@ import java.awt.Polygon;
|
||||
import java.awt.Shape;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.annotation.Nullable;
|
||||
import net.runelite.api.annotations.VisibleForDevtools;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
@@ -105,10 +106,6 @@ public interface Actor extends Renderable, Locatable
|
||||
*/
|
||||
LocalPoint getLocalLocation();
|
||||
|
||||
void setIdlePoseAnimation(int animation);
|
||||
|
||||
void setPoseAnimation(int animation);
|
||||
|
||||
/**
|
||||
* Get the index of the PoseFrame (the index as it appears in the sequenceDefinition "frames" array).
|
||||
*/
|
||||
@@ -138,22 +135,84 @@ public interface Actor extends Renderable, Locatable
|
||||
int getAnimation();
|
||||
|
||||
/**
|
||||
* Gets the secondary animation the actor is performing.
|
||||
* Gets the secondary animation the actor is performing. Usually an idle animation, or one of the walking ones.
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getPoseAnimation();
|
||||
|
||||
@VisibleForDevtools
|
||||
void setPoseAnimation(int animation);
|
||||
|
||||
/**
|
||||
* If this is equal to the pose animation, the pose animation is ignored when
|
||||
* you are doing another action.
|
||||
* The idle pose animation. If the actor is not walking or otherwise animating, this will be used
|
||||
* for their pose animation.
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getIdlePoseAnimation();
|
||||
|
||||
@VisibleForDevtools
|
||||
void setIdlePoseAnimation(int animation);
|
||||
|
||||
/**
|
||||
* Animation used for rotating left if the actor is also not walking
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getIdleRotateLeft();
|
||||
|
||||
/**
|
||||
* Animation used for rotating right if the actor is also not walking
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getIdleRotateRight();
|
||||
|
||||
/**
|
||||
* Animation used for walking
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getWalkAnimation();
|
||||
|
||||
/**
|
||||
* Animation used for rotating left while walking
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getWalkRotateLeft();
|
||||
|
||||
/**
|
||||
* Animation used for rotating right while walking
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getWalkRotateRight();
|
||||
|
||||
/**
|
||||
* Animation used for an about-face while walking
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getWalkRotate180();
|
||||
|
||||
/**
|
||||
* Animation used for running
|
||||
*
|
||||
* @return the animation ID
|
||||
* @see AnimationID
|
||||
*/
|
||||
int getRunAnimation();
|
||||
|
||||
/**
|
||||
* Sets an animation for the actor to perform.
|
||||
*
|
||||
@@ -291,16 +350,18 @@ public interface Actor extends Renderable, Locatable
|
||||
|
||||
int getTurnRightAnimation();
|
||||
|
||||
int getWalkAnimation();
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
int getWalkBackAnimation();
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
int getWalkLeftAnimation();
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
int getWalkRightAnimation();
|
||||
|
||||
int getRunAnimation();
|
||||
|
||||
/**
|
||||
* Returns true if this NPC has died
|
||||
*
|
||||
|
||||
@@ -395,11 +395,16 @@ public enum Varbits
|
||||
MULTICOMBAT_AREA(4605),
|
||||
|
||||
/**
|
||||
* Kingdom Management
|
||||
* Kingdom of Miscellania Management
|
||||
* Kingdom Approval is represented as a 7-bit unsigned integer; 127 corresponds to 100% approval
|
||||
*/
|
||||
KINGDOM_FAVOR(72),
|
||||
KINGDOM_APPROVAL(72),
|
||||
KINGDOM_COFFER(74),
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
KINGDOM_FAVOR(72),
|
||||
|
||||
/**
|
||||
* The Hand in the Sand quest status
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,7 @@ package net.runelite.api.widgets;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Collection;
|
||||
import javax.annotation.Nullable;
|
||||
import net.runelite.api.FontTypeFace;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.SpritePixels;
|
||||
@@ -117,6 +118,7 @@ public interface Widget
|
||||
/**
|
||||
* Gets the dynamic children of this widget in a sparse array
|
||||
*/
|
||||
@Nullable
|
||||
Widget[] getChildren();
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,6 +53,7 @@ dependencies {
|
||||
compileOnly(group = "net.runelite", name = "orange-extensions", version = "1.0")
|
||||
|
||||
implementation(project(":http-api"))
|
||||
implementation(project(":runelite-jshell"))
|
||||
implementation(group = "ch.qos.logback", name = "logback-classic", version = "1.2.3")
|
||||
implementation(group = "com.google.code.gson", name = "gson", version = "2.8.5")
|
||||
implementation(group = "com.google.guava", name = "guava", version = "23.2-jre")
|
||||
|
||||
@@ -51,26 +51,20 @@ import net.runelite.client.util.ReflectUtil;
|
||||
@ThreadSafe
|
||||
public class EventBus
|
||||
{
|
||||
@FunctionalInterface
|
||||
public interface SubscriberMethod
|
||||
{
|
||||
void invoke(Object event);
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class Subscriber
|
||||
public static class Subscriber
|
||||
{
|
||||
private final Object object;
|
||||
private final Method method;
|
||||
private final float priority;
|
||||
@EqualsAndHashCode.Exclude
|
||||
private final SubscriberMethod lamda;
|
||||
private final Consumer<Object> lambda;
|
||||
|
||||
void invoke(final Object arg) throws Exception
|
||||
{
|
||||
if (lamda != null)
|
||||
if (lambda != null)
|
||||
{
|
||||
lamda.invoke(arg);
|
||||
lambda.accept(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -80,7 +74,9 @@ public class EventBus
|
||||
}
|
||||
|
||||
private final Consumer<Throwable> exceptionHandler;
|
||||
private ImmutableMultimap<Class, Subscriber> subscribers = ImmutableMultimap.of();
|
||||
|
||||
@Nonnull
|
||||
private ImmutableMultimap<Class<?>, Subscriber> subscribers = ImmutableMultimap.of();
|
||||
|
||||
/**
|
||||
* Instantiates EventBus with default exception handler
|
||||
@@ -99,13 +95,8 @@ public class EventBus
|
||||
*/
|
||||
public synchronized void register(@Nonnull final Object object)
|
||||
{
|
||||
final ImmutableMultimap.Builder<Class, Subscriber> builder = ImmutableMultimap.builder();
|
||||
|
||||
if (subscribers != null)
|
||||
{
|
||||
final ImmutableMultimap.Builder<Class<?>, Subscriber> builder = ImmutableMultimap.builder();
|
||||
builder.putAll(subscribers);
|
||||
}
|
||||
|
||||
builder.orderValuesBy(Comparator.comparing(Subscriber::getPriority).reversed()
|
||||
.thenComparing(s -> s.object.getClass().getName()));
|
||||
|
||||
@@ -138,7 +129,7 @@ public class EventBus
|
||||
}
|
||||
|
||||
method.setAccessible(true);
|
||||
SubscriberMethod lambda = null;
|
||||
Consumer<Object> lambda = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -147,14 +138,14 @@ public class EventBus
|
||||
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
|
||||
final CallSite site = LambdaMetafactory.metafactory(
|
||||
caller,
|
||||
"invoke",
|
||||
MethodType.methodType(SubscriberMethod.class, clazz),
|
||||
"accept",
|
||||
MethodType.methodType(Consumer.class, clazz),
|
||||
subscription.changeParameterType(0, Object.class),
|
||||
target,
|
||||
subscription);
|
||||
|
||||
final MethodHandle factory = site.getTarget();
|
||||
lambda = (SubscriberMethod) factory.bindTo(object).invokeExact();
|
||||
lambda = (Consumer<Object>) factory.bindTo(object).invokeExact();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
@@ -170,6 +161,21 @@ public class EventBus
|
||||
subscribers = builder.build();
|
||||
}
|
||||
|
||||
public synchronized <T> Subscriber register(Class<T> clazz, Consumer<T> subFn, float priority)
|
||||
{
|
||||
final ImmutableMultimap.Builder<Class<?>, Subscriber> builder = ImmutableMultimap.builder();
|
||||
builder.putAll(subscribers);
|
||||
builder.orderValuesBy(Comparator.comparing(Subscriber::getPriority).reversed()
|
||||
.thenComparing(s -> s.object.getClass().getName()));
|
||||
|
||||
Subscriber sub = new Subscriber(subFn, null, priority, (Consumer<Object>) subFn);
|
||||
builder.put(clazz, sub);
|
||||
|
||||
subscribers = builder.build();
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all subscribed methods from provided subscriber object.
|
||||
*
|
||||
@@ -177,12 +183,7 @@ public class EventBus
|
||||
*/
|
||||
public synchronized void unregister(@Nonnull final Object object)
|
||||
{
|
||||
if (subscribers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Multimap<Class, Subscriber> map = HashMultimap.create();
|
||||
final Multimap<Class<?>, Subscriber> map = HashMultimap.create();
|
||||
map.putAll(subscribers);
|
||||
|
||||
for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
|
||||
@@ -204,6 +205,21 @@ public class EventBus
|
||||
subscribers = ImmutableMultimap.copyOf(map);
|
||||
}
|
||||
|
||||
public synchronized void unregister(Subscriber sub)
|
||||
{
|
||||
if (sub == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Multimap<Class<?>, Subscriber> map = HashMultimap.create();
|
||||
map.putAll(subscribers);
|
||||
|
||||
map.values().remove(sub);
|
||||
|
||||
subscribers = ImmutableMultimap.copyOf(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts provided event to all registered subscribers. Subscriber calls are invoked immediately,
|
||||
* ordered by priority then their declaring class' name.
|
||||
|
||||
@@ -253,6 +253,22 @@ public enum ItemMapping
|
||||
ITEM_VOLATILE_ORB(VOLATILE_ORB, VOLATILE_NIGHTMARE_STAFF),
|
||||
ITEM_NIGHTMARE_STAFF(NIGHTMARE_STAFF, ELDRITCH_NIGHTMARE_STAFF, HARMONISED_NIGHTMARE_STAFF, VOLATILE_NIGHTMARE_STAFF),
|
||||
|
||||
// Trouver Parchment
|
||||
ITEM_TROUVER_PARCHMENT(
|
||||
TROUVER_PARCHMENT, INFERNAL_MAX_CAPE_L, FIRE_MAX_CAPE_L, ASSEMBLER_MAX_CAPE_L, BRONZE_DEFENDER_L, IRON_DEFENDER_L, STEEL_DEFENDER_L, BLACK_DEFENDER_L, MITHRIL_DEFENDER_L, ADAMANT_DEFENDER_L,
|
||||
RUNE_DEFENDER_L, DRAGON_DEFENDER_L, DECORATIVE_SWORD_L, DECORATIVE_ARMOUR_L, DECORATIVE_ARMOUR_L_24159, DECORATIVE_HELM_L, DECORATIVE_SHIELD_L, DECORATIVE_ARMOUR_L_24162, DECORATIVE_ARMOUR_L_24163, DECORATIVE_ARMOUR_L_24164,
|
||||
DECORATIVE_ARMOUR_L_24165, DECORATIVE_ARMOUR_L_24166, DECORATIVE_ARMOUR_L_24167, DECORATIVE_ARMOUR_L_24168, SARADOMIN_HALO_L, ZAMORAK_HALO_L, GUTHIX_HALO_L, HEALER_HAT_L, FIGHTER_HAT_L, RANGER_HAT_L,
|
||||
FIGHTER_TORSO_L, PENANCE_SKIRT_L, VOID_KNIGHT_TOP_L, ELITE_VOID_TOP_L, VOID_KNIGHT_ROBE_L, ELITE_VOID_ROBE_L, VOID_KNIGHT_MACE_L, VOID_KNIGHT_GLOVES_L, VOID_MAGE_HELM_L, VOID_RANGER_HELM_L,
|
||||
VOID_MELEE_HELM_L, AVERNIC_DEFENDER_L, ARMADYL_HALO_L, BANDOS_HALO_L, SEREN_HALO_L, ANCIENT_HALO_L, BRASSICA_HALO_L, AVAS_ASSEMBLER_L, FIRE_CAPE_L, INFERNAL_CAPE_L, IMBUED_SARADOMIN_MAX_CAPE_L,
|
||||
IMBUED_ZAMORAK_MAX_CAPE_L, IMBUED_GUTHIX_MAX_CAPE_L, IMBUED_SARADOMIN_CAPE_L, IMBUED_ZAMORAK_CAPE_L, IMBUED_GUTHIX_CAPE_L, RUNE_POUCH_L, RUNNER_HAT_L, DECORATIVE_BOOTS_L, DECORATIVE_FULL_HELM_L),
|
||||
ITEM_TROUVER_PARCHMENT_REFUND_LARGE(
|
||||
COINS_995, 475000L, INFERNAL_MAX_CAPE_L, FIRE_MAX_CAPE_L, ASSEMBLER_MAX_CAPE_L, RUNE_DEFENDER_L, DRAGON_DEFENDER_L, DECORATIVE_SWORD_L, DECORATIVE_ARMOUR_L, DECORATIVE_ARMOUR_L_24159, DECORATIVE_HELM_L, DECORATIVE_SHIELD_L,
|
||||
DECORATIVE_ARMOUR_L_24162, DECORATIVE_ARMOUR_L_24163, DECORATIVE_ARMOUR_L_24164, DECORATIVE_ARMOUR_L_24165, DECORATIVE_ARMOUR_L_24166, DECORATIVE_ARMOUR_L_24167, DECORATIVE_ARMOUR_L_24168, SARADOMIN_HALO_L,
|
||||
ZAMORAK_HALO_L, GUTHIX_HALO_L, HEALER_HAT_L, FIGHTER_HAT_L, RANGER_HAT_L, FIGHTER_TORSO_L, PENANCE_SKIRT_L, VOID_KNIGHT_TOP_L, ELITE_VOID_TOP_L, VOID_KNIGHT_ROBE_L, ELITE_VOID_ROBE_L, VOID_KNIGHT_MACE_L,
|
||||
VOID_KNIGHT_GLOVES_L, VOID_MAGE_HELM_L, VOID_RANGER_HELM_L, VOID_MELEE_HELM_L, AVERNIC_DEFENDER_L, ARMADYL_HALO_L, BANDOS_HALO_L, SEREN_HALO_L, ANCIENT_HALO_L, BRASSICA_HALO_L, AVAS_ASSEMBLER_L,
|
||||
FIRE_CAPE_L, INFERNAL_CAPE_L, IMBUED_SARADOMIN_MAX_CAPE_L, IMBUED_ZAMORAK_MAX_CAPE_L, IMBUED_GUTHIX_MAX_CAPE_L, IMBUED_SARADOMIN_CAPE_L, IMBUED_ZAMORAK_CAPE_L, IMBUED_GUTHIX_CAPE_L, RUNE_POUCH_L, RUNNER_HAT_L, DECORATIVE_BOOTS_L, DECORATIVE_FULL_HELM_L),
|
||||
ITEM_TROUVER_PARCHMENT_REFUND_SMALL(COINS_995, 47500L, BRONZE_DEFENDER_L, IRON_DEFENDER_L, STEEL_DEFENDER_L, BLACK_DEFENDER_L, MITHRIL_DEFENDER_L, ADAMANT_DEFENDER_L),
|
||||
|
||||
// Crystal items
|
||||
ITEM_CRYSTAL_TOOL_SEED(CRYSTAL_TOOL_SEED, CRYSTAL_AXE, CRYSTAL_AXE_INACTIVE, CRYSTAL_HARPOON, CRYSTAL_HARPOON_INACTIVE, CRYSTAL_PICKAXE, CRYSTAL_PICKAXE_INACTIVE),
|
||||
ITEM_CRYSTAL_AXE(DRAGON_AXE, CRYSTAL_AXE, CRYSTAL_AXE_INACTIVE),
|
||||
|
||||
@@ -70,7 +70,7 @@ import net.runelite.client.util.QuantityFormatter;
|
||||
@PluginDescriptor(
|
||||
name = "Bank",
|
||||
description = "Modifications to the banking interface",
|
||||
tags = {"grand", "exchange", "high", "alchemy", "prices", "deposit"}
|
||||
tags = {"grand", "exchange", "high", "alchemy", "prices", "deposit", "pin"}
|
||||
)
|
||||
@Slf4j
|
||||
public class BankPlugin extends Plugin
|
||||
@@ -238,12 +238,15 @@ public class BankPlugin extends Plugin
|
||||
|
||||
log.debug("Bank pin keypress");
|
||||
|
||||
final String input = client.getVar(VarClientStr.CHATBOX_TYPED_TEXT);
|
||||
final String chatboxTypedText = client.getVar(VarClientStr.CHATBOX_TYPED_TEXT);
|
||||
final String inputText = client.getVar(VarClientStr.INPUT_TEXT);
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
// reset chatbox input to avoid pin going to chatbox..
|
||||
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, input);
|
||||
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, chatboxTypedText);
|
||||
client.runScript(ScriptID.CHAT_PROMPT_INIT);
|
||||
client.setVar(VarClientStr.INPUT_TEXT, inputText);
|
||||
client.runScript(ScriptID.CHAT_TEXT_INPUT_REBUILD, "");
|
||||
|
||||
client.runScript(onOpListener);
|
||||
});
|
||||
|
||||
@@ -481,12 +481,16 @@ public class ChatCommandsPlugin extends Plugin
|
||||
advLogLoaded = false;
|
||||
|
||||
Widget adventureLog = client.getWidget(WidgetInfo.ADVENTURE_LOG);
|
||||
|
||||
if (adventureLog != null)
|
||||
{
|
||||
Matcher advLogExploitsText = ADVENTURE_LOG_TITLE_PATTERN.matcher(adventureLog.getChild(ADV_LOG_EXPLOITS_TEXT_INDEX).getText());
|
||||
if (advLogExploitsText.find())
|
||||
{
|
||||
pohOwner = advLogExploitsText.group(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bossLogLoaded && (pohOwner == null || pohOwner.equals(client.getLocalPlayer().getName())))
|
||||
{
|
||||
|
||||
@@ -172,6 +172,18 @@ public class ChatNotificationsPlugin extends Plugin
|
||||
notifier.notify(Text.removeTags(chatMessage.getName()) + ": " + chatMessage.getMessage());
|
||||
}
|
||||
break;
|
||||
case PRIVATECHATOUT:
|
||||
return;
|
||||
case MODCHAT:
|
||||
case PUBLICCHAT:
|
||||
case FRIENDSCHAT:
|
||||
case AUTOTYPER:
|
||||
case MODAUTOTYPER:
|
||||
if (client.getLocalPlayer() != null && Text.toJagexName(Text.removeTags(chatMessage.getName())).equals(client.getLocalPlayer().getName()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case CONSOLE:
|
||||
// Don't notify for notification messages
|
||||
if (chatMessage.getName().equals(runeliteTitle))
|
||||
|
||||
@@ -159,7 +159,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll, Nam
|
||||
new SkillChallengeClue("Craft multiple cosmic runes from a single essence.", item(ItemID.PURE_ESSENCE)),
|
||||
new SkillChallengeClue("Plant a watermelon seed.", item(ItemID.RAKE), item(ItemID.SEED_DIBBER), xOfItem(ItemID.WATERMELON_SEED, 3)),
|
||||
new SkillChallengeClue("Activate the Chivalry prayer."),
|
||||
new SkillChallengeClue("Hand in a Tier 2 or higher set of Shayzien supply armour", "take the lovakengj armourers a boxed set of shayzien supply armour at tier 2 or above.", any("Shayzien Supply Set (Tier 2 or higher)", item(ItemID.SHAYZIEN_SUPPLY_SET_2), item(ItemID.SHAYZIEN_SUPPLY_SET_3), item(ItemID.SHAYZIEN_SUPPLY_SET_4), item(ItemID.SHAYZIEN_SUPPLY_SET_5))),
|
||||
new SkillChallengeClue("Hand in a Tier 2 or higher set of Shayzien supply armour. (Requires 11 lovakite bars)", "take the lovakengj armourers a boxed set of shayzien supply armour at tier 2 or above.", any("Shayzien Supply Set (Tier 2 or higher)", item(ItemID.SHAYZIEN_SUPPLY_SET_2), item(ItemID.SHAYZIEN_SUPPLY_SET_3), item(ItemID.SHAYZIEN_SUPPLY_SET_4), item(ItemID.SHAYZIEN_SUPPLY_SET_5))),
|
||||
// Master Sherlock Tasks
|
||||
new SkillChallengeClue("Equip an abyssal whip in front of the abyssal demons of the Slayer Tower.", true, any("Abyssal Whip", item(ItemID.ABYSSAL_WHIP), item(ItemID.FROZEN_ABYSSAL_WHIP), item(ItemID.VOLCANIC_ABYSSAL_WHIP))),
|
||||
new SkillChallengeClue("Smith a runite med helm.", item(ItemID.HAMMER), item(ItemID.RUNITE_BAR)),
|
||||
|
||||
@@ -62,7 +62,7 @@ public enum HotColdLocation
|
||||
ASGARNIA_CRAFT_GUILD(new WorldPoint(2917, 3295, 0), ASGARNIA, "Outside the Crafting Guild cow pen.", BRASSICAN_MAGE),
|
||||
ASGARNIA_RIMMINGTON(new WorldPoint(2976, 3239, 0), ASGARNIA, "In the centre of the Rimmington mine.", BRASSICAN_MAGE),
|
||||
ASGARNIA_MUDSKIPPER(new WorldPoint(2987, 3110, 0), ASGARNIA, "Mudskipper Point, near the starfish in the south-west corner.", BRASSICAN_MAGE),
|
||||
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.", BRASSICAN_MAGE),
|
||||
ASGARNIA_TROLL(new WorldPoint(2910, 3615, 0), ASGARNIA, "The Troll arena, where the player fights Dad during the Troll Stronghold quest. Bring climbing boots if travelling from Burthorpe.", BRASSICAN_MAGE),
|
||||
DESERT_GENIE(new WorldPoint(3359, 2912, 0), DESERT, "West of Nardah genie cave.", BRASSICAN_MAGE),
|
||||
DESERT_ALKHARID_MINE(new WorldPoint(3279, 3263, 0), DESERT, "West of Al Kharid mine.", BRASSICAN_MAGE),
|
||||
DESERT_MENAPHOS_GATE(new WorldPoint(3223, 2820, 0), DESERT, "North of Menaphos gate.", BRASSICAN_MAGE),
|
||||
@@ -117,7 +117,7 @@ public enum HotColdLocation
|
||||
KARAMJA_MUSA_POINT(new WorldPoint(2913, 3169, 0), KARAMJA, "Musa Point, banana plantation.", BRASSICAN_MAGE),
|
||||
KARAMJA_BRIMHAVEN_FRUIT_TREE(new WorldPoint(2782, 3215, 0), KARAMJA, "Brimhaven, east of the fruit tree patch.", BRASSICAN_MAGE),
|
||||
KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2718, 3167, 0), KARAMJA, "West of Brimhaven.", BRASSICAN_MAGE),
|
||||
KARAMJA_GLIDER(new WorldPoint(2966, 2975, 0), KARAMJA, "West of the gnome glider.", BRASSICAN_MAGE),
|
||||
KARAMJA_GLIDER(new WorldPoint(2966, 2976, 0), KARAMJA, "West of the gnome glider.", BRASSICAN_MAGE),
|
||||
KARAMJA_KHARAZI_NE(new WorldPoint(2904, 2925, 0), KARAMJA, "North-eastern part of Kharazi Jungle.", BRASSICAN_MAGE),
|
||||
KARAMJA_KHARAZI_SW(new WorldPoint(2786, 2899, 0), KARAMJA, "South-western part of Kharazi Jungle.", BRASSICAN_MAGE),
|
||||
KARAMJA_CRASH_ISLAND(new WorldPoint(2909, 2737, 0), KARAMJA, "Northern part of Crash Island.", BRASSICAN_MAGE),
|
||||
@@ -146,7 +146,7 @@ public enum HotColdLocation
|
||||
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2359, 3564, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry.", BRASSICAN_MAGE),
|
||||
WESTERN_PROVINCE_ARANDAR(new WorldPoint(2370, 3319, 0), WESTERN_PROVINCE, "South-west of the crystal gate to Arandar.", ANCIENT_WIZARDS),
|
||||
WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2268, 3242, 0), WESTERN_PROVINCE, "East of Iorwerth Camp.", BRASSICAN_MAGE),
|
||||
WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Iorwerth Camp.", BRASSICAN_MAGE),
|
||||
WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2177, 3282, 0), WESTERN_PROVINCE, "North-west of Iorwerth Camp.", BRASSICAN_MAGE),
|
||||
WESTERN_PROVINCE_LLETYA(new WorldPoint(2337, 3166, 0), WESTERN_PROVINCE, "In Lletya.", BRASSICAN_MAGE),
|
||||
WESTERN_PROVINCE_TYRAS(new WorldPoint(2206, 3158, 0), WESTERN_PROVINCE, "Near Tyras Camp.", BRASSICAN_MAGE),
|
||||
WESTERN_PROVINCE_ZULANDRA(new WorldPoint(2196, 3057, 0), WESTERN_PROVINCE, "The northern house at Zul-Andra.", BRASSICAN_MAGE),
|
||||
|
||||
@@ -196,7 +196,7 @@ public class CookingPlugin extends Plugin
|
||||
|
||||
}
|
||||
else if (message.startsWith("You accidentally burn")
|
||||
|| message.startsWith("You burn")
|
||||
|| message.equals("You burn the mushroom in the fire.")
|
||||
|| message.startsWith("Unfortunately the Jubbly")
|
||||
|| message.startsWith("You accidentally spoil"))
|
||||
{
|
||||
|
||||
@@ -80,7 +80,7 @@ public class CrowdsourcingCooking
|
||||
|| message.startsWith("You roast a")
|
||||
|| message.startsWith("You spit-roast")
|
||||
|| message.startsWith("You cook")
|
||||
|| message.startsWith("You burn")
|
||||
|| message.equals("You burn the mushroom in the fire.")
|
||||
|| message.startsWith("Eventually the Jubbly")
|
||||
|| message.startsWith("Unfortunately the Jubbly")
|
||||
|| message.startsWith("You accidentally burn")
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.awt.Color;
|
||||
import javax.swing.JButton;
|
||||
import lombok.Getter;
|
||||
|
||||
class DevToolsButton extends JButton
|
||||
public class DevToolsButton extends JButton
|
||||
{
|
||||
@Getter
|
||||
private boolean active;
|
||||
@@ -53,4 +53,20 @@ class DevToolsButton extends JButton
|
||||
setBackground(null);
|
||||
}
|
||||
}
|
||||
|
||||
void addFrame(DevToolsFrame frame)
|
||||
{
|
||||
frame.setDevToolsButton(this);
|
||||
addActionListener(ev ->
|
||||
{
|
||||
if (isActive())
|
||||
{
|
||||
frame.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.open();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.devtools;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import javax.swing.JFrame;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Setter;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
|
||||
public class DevToolsFrame extends JFrame
|
||||
{
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
protected DevToolsButton devToolsButton;
|
||||
|
||||
public DevToolsFrame()
|
||||
{
|
||||
setIconImage(ClientUI.ICON);
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
close();
|
||||
devToolsButton.setActive(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void open()
|
||||
{
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.devtools;
|
||||
|
||||
import com.google.inject.ProvisionException;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.TrayIcon;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@@ -32,6 +33,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.MenuAction;
|
||||
@@ -44,6 +46,7 @@ import net.runelite.client.ui.overlay.infobox.Counter;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
@Slf4j
|
||||
class DevToolsPanel extends PluginPanel
|
||||
{
|
||||
private final Client client;
|
||||
@@ -129,30 +132,10 @@ class DevToolsPanel extends PluginPanel
|
||||
});
|
||||
|
||||
container.add(plugin.getWidgetInspector());
|
||||
plugin.getWidgetInspector().addActionListener((ev) ->
|
||||
{
|
||||
if (plugin.getWidgetInspector().isActive())
|
||||
{
|
||||
widgetInspector.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
widgetInspector.open();
|
||||
}
|
||||
});
|
||||
plugin.getWidgetInspector().addFrame(widgetInspector);
|
||||
|
||||
container.add(plugin.getVarInspector());
|
||||
plugin.getVarInspector().addActionListener((ev) ->
|
||||
{
|
||||
if (plugin.getVarInspector().isActive())
|
||||
{
|
||||
varInspector.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
varInspector.open();
|
||||
}
|
||||
});
|
||||
plugin.getVarInspector().addFrame(varInspector);
|
||||
|
||||
container.add(plugin.getSoundEffects());
|
||||
|
||||
@@ -164,17 +147,7 @@ class DevToolsPanel extends PluginPanel
|
||||
container.add(notificationBtn);
|
||||
|
||||
container.add(plugin.getScriptInspector());
|
||||
plugin.getScriptInspector().addActionListener((ev) ->
|
||||
{
|
||||
if (plugin.getScriptInspector().isActive())
|
||||
{
|
||||
scriptInspector.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
scriptInspector.open();
|
||||
}
|
||||
});
|
||||
plugin.getScriptInspector().addFrame(scriptInspector);
|
||||
|
||||
final JButton newInfoboxBtn = new JButton("Infobox");
|
||||
newInfoboxBtn.addActionListener(e ->
|
||||
@@ -198,22 +171,27 @@ class DevToolsPanel extends PluginPanel
|
||||
container.add(clearInfoboxBtn);
|
||||
|
||||
container.add(plugin.getInventoryInspector());
|
||||
plugin.getInventoryInspector().addActionListener((ev) ->
|
||||
{
|
||||
if (plugin.getInventoryInspector().isActive())
|
||||
{
|
||||
inventoryInspector.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
inventoryInspector.open();
|
||||
}
|
||||
});
|
||||
plugin.getInventoryInspector().addFrame(inventoryInspector);
|
||||
|
||||
final JButton disconnectBtn = new JButton("Disconnect");
|
||||
disconnectBtn.addActionListener(e -> clientThread.invoke(() -> client.setGameState(GameState.CONNECTION_LOST)));
|
||||
container.add(disconnectBtn);
|
||||
|
||||
try
|
||||
{
|
||||
ShellFrame sf = plugin.getInjector().getInstance(ShellFrame.class);
|
||||
container.add(plugin.getShell());
|
||||
plugin.getShell().addFrame(sf);
|
||||
}
|
||||
catch (LinkageError | ProvisionException e)
|
||||
{
|
||||
log.debug("Shell is not supported", e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.info("Shell couldn't be loaded", e);
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ public class DevToolsPlugin extends Plugin
|
||||
private DevToolsButton soundEffects;
|
||||
private DevToolsButton scriptInspector;
|
||||
private DevToolsButton inventoryInspector;
|
||||
private DevToolsButton shell;
|
||||
private NavigationButton navButton;
|
||||
|
||||
@Provides
|
||||
@@ -187,6 +188,7 @@ public class DevToolsPlugin extends Plugin
|
||||
soundEffects = new DevToolsButton("Sound Effects");
|
||||
scriptInspector = new DevToolsButton("Script Inspector");
|
||||
inventoryInspector = new DevToolsButton("Inventory Inspector");
|
||||
shell = new DevToolsButton("Shell");
|
||||
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(locationOverlay);
|
||||
|
||||
@@ -28,8 +28,6 @@ import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -39,7 +37,6 @@ import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
@@ -65,7 +62,7 @@ import net.runelite.client.ui.ColorScheme;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
class InventoryInspector extends JFrame
|
||||
class InventoryInspector extends DevToolsFrame
|
||||
{
|
||||
private static final int MAX_LOG_ENTRIES = 25;
|
||||
|
||||
@@ -80,7 +77,7 @@ class InventoryInspector extends JFrame
|
||||
private final InventoryDeltaPanel deltaPanel;
|
||||
|
||||
@Inject
|
||||
InventoryInspector(Client client, EventBus eventBus, DevToolsPlugin plugin, ItemManager itemManager, ClientThread clientThread)
|
||||
InventoryInspector(Client client, EventBus eventBus, ItemManager itemManager, ClientThread clientThread)
|
||||
{
|
||||
this.client = client;
|
||||
this.eventBus = eventBus;
|
||||
@@ -92,18 +89,6 @@ class InventoryInspector extends JFrame
|
||||
setTitle("OpenOSRS Inventory Inspector");
|
||||
setIconImage(ClientUI.ICON);
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
// Reset highlight on close
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
close();
|
||||
plugin.getInventoryInspector().setActive(false);
|
||||
}
|
||||
});
|
||||
|
||||
tree.setBorder(new EmptyBorder(2, 2, 2, 2));
|
||||
tree.setRootVisible(false);
|
||||
tree.setShowsRootHandles(true);
|
||||
@@ -175,19 +160,19 @@ class InventoryInspector extends JFrame
|
||||
pack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open()
|
||||
{
|
||||
eventBus.register(this);
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
eventBus.unregister(this);
|
||||
clearTracker();
|
||||
setVisible(false);
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
@@ -31,8 +31,6 @@ import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
@@ -42,7 +40,6 @@ import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
@@ -68,14 +65,13 @@ import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.DynamicGridLayout;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Slf4j
|
||||
public class ScriptInspector extends JFrame
|
||||
public class ScriptInspector extends DevToolsFrame
|
||||
{
|
||||
// These scripts are the only ones that fire every client tick regardless of location.
|
||||
private final static String DEFAULT_BLACKLIST = "3174,1004";
|
||||
@@ -139,28 +135,16 @@ public class ScriptInspector extends JFrame
|
||||
}
|
||||
|
||||
@Inject
|
||||
ScriptInspector(Client client, EventBus eventBus, DevToolsPlugin plugin, ConfigManager configManager)
|
||||
ScriptInspector(Client client, EventBus eventBus, ConfigManager configManager)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.client = client;
|
||||
this.configManager = configManager;
|
||||
|
||||
setTitle("OpenOSRS Script Inspector");
|
||||
setIconImage(ClientUI.ICON);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
close();
|
||||
plugin.getScriptInspector().setActive(false);
|
||||
}
|
||||
});
|
||||
|
||||
tracker.setLayout(new DynamicGridLayout(0, 1, 0, 3));
|
||||
|
||||
final JPanel leftSide = new JPanel();
|
||||
@@ -344,14 +328,14 @@ public class ScriptInspector extends JFrame
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open()
|
||||
{
|
||||
eventBus.register(this);
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
configManager.setConfiguration("devtools", "highlights",
|
||||
@@ -360,7 +344,7 @@ public class ScriptInspector extends JFrame
|
||||
Text.toCSV(Lists.transform(new ArrayList<>(blacklist), String::valueOf)));
|
||||
currentNode = null;
|
||||
eventBus.unregister(this);
|
||||
setVisible(false);
|
||||
super.close();
|
||||
}
|
||||
|
||||
private void addScriptLog(ScriptTreeNode treeNode)
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.devtools;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.jshell.ShellPanel;
|
||||
|
||||
@Singleton
|
||||
class ShellFrame extends DevToolsFrame
|
||||
{
|
||||
private final ShellPanel shellPanel;
|
||||
|
||||
@Inject
|
||||
ShellFrame(ClientThread clientThread, ScheduledExecutorService executor)
|
||||
{
|
||||
this.shellPanel = new ShellPanel(executor)
|
||||
{
|
||||
@Override
|
||||
protected void invokeOnClientThread(Runnable r)
|
||||
{
|
||||
clientThread.invoke(r);
|
||||
}
|
||||
};
|
||||
setContentPane(shellPanel);
|
||||
|
||||
setTitle("OpenOSRS Shell");
|
||||
|
||||
pack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open()
|
||||
{
|
||||
shellPanel.switchContext(RuneLite.getInjector());
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
super.close();
|
||||
shellPanel.freeContext();
|
||||
}
|
||||
}
|
||||
@@ -32,15 +32,12 @@ import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
@@ -62,13 +59,12 @@ import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.DynamicGridLayout;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
|
||||
@Slf4j
|
||||
class VarInspector extends JFrame
|
||||
class VarInspector extends DevToolsFrame
|
||||
{
|
||||
@Getter
|
||||
private enum VarType
|
||||
@@ -106,28 +102,16 @@ class VarInspector extends JFrame
|
||||
private Map<Integer, Object> varcs = null;
|
||||
|
||||
@Inject
|
||||
VarInspector(Client client, ClientThread clientThread, EventBus eventBus, DevToolsPlugin plugin)
|
||||
VarInspector(Client client, ClientThread clientThread, EventBus eventBus)
|
||||
{
|
||||
this.client = client;
|
||||
this.clientThread = clientThread;
|
||||
this.eventBus = eventBus;
|
||||
|
||||
setTitle("OpenOSRS Var Inspector");
|
||||
setIconImage(ClientUI.ICON);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
close();
|
||||
plugin.getVarInspector().setActive(false);
|
||||
}
|
||||
});
|
||||
|
||||
tracker.setLayout(new DynamicGridLayout(0, 1, 0, 3));
|
||||
|
||||
final JPanel trackerWrapper = new JPanel();
|
||||
@@ -332,6 +316,7 @@ class VarInspector extends JFrame
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open()
|
||||
{
|
||||
if (oldVarps == null)
|
||||
@@ -361,16 +346,15 @@ class VarInspector extends JFrame
|
||||
});
|
||||
|
||||
eventBus.register(this);
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
super.close();
|
||||
tracker.removeAll();
|
||||
eventBus.unregister(this);
|
||||
setVisible(false);
|
||||
varcs = null;
|
||||
varbits = null;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ import com.google.inject.Singleton;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
@@ -43,7 +41,6 @@ import java.util.Stack;
|
||||
import java.util.stream.Stream;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
@@ -73,13 +70,12 @@ import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
class WidgetInspector extends JFrame
|
||||
class WidgetInspector extends DevToolsFrame
|
||||
{
|
||||
private static final Map<Integer, WidgetInfo> widgetIdMap = new HashMap<>();
|
||||
|
||||
@@ -123,7 +119,6 @@ class WidgetInspector extends JFrame
|
||||
ClientThread clientThread,
|
||||
WidgetInfoTableModel infoTableModel,
|
||||
DevToolsConfig config,
|
||||
DevToolsPlugin plugin,
|
||||
EventBus eventBus,
|
||||
Provider<WidgetInspectorOverlay> overlay,
|
||||
OverlayManager overlayManager)
|
||||
@@ -138,18 +133,6 @@ class WidgetInspector extends JFrame
|
||||
eventBus.register(this);
|
||||
|
||||
setTitle("OpenOSRS Widget Inspector");
|
||||
setIconImage(ClientUI.ICON);
|
||||
|
||||
// Reset highlight on close
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
close();
|
||||
plugin.getWidgetInspector().setActive(false);
|
||||
}
|
||||
});
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
@@ -402,21 +385,21 @@ class WidgetInspector extends JFrame
|
||||
return widgetIdMap.get(packedId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open()
|
||||
{
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
super.open();
|
||||
overlayManager.add(this.overlay.get());
|
||||
clientThread.invokeLater(this::addPickerWidget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
overlayManager.remove(this.overlay.get());
|
||||
clientThread.invokeLater(this::removePickerWidget);
|
||||
setSelectedWidget(null, -1, false);
|
||||
setVisible(false);
|
||||
super.close();
|
||||
}
|
||||
|
||||
private void removePickerWidget()
|
||||
|
||||
@@ -72,11 +72,22 @@ public interface DiscordConfig extends Config
|
||||
return 5;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMainMenu",
|
||||
name = "Main Menu",
|
||||
description = "Show status when in main menu",
|
||||
position = 3
|
||||
)
|
||||
default boolean showMainMenu()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showSkillActivity",
|
||||
name = "Skilling",
|
||||
description = "Show your activity while training skills",
|
||||
position = 3
|
||||
position = 4
|
||||
)
|
||||
default boolean showSkillingActivity()
|
||||
{
|
||||
@@ -87,7 +98,7 @@ public interface DiscordConfig extends Config
|
||||
keyName = "showBossActivity",
|
||||
name = "Bosses",
|
||||
description = "Show your activity and location while at bosses",
|
||||
position = 4
|
||||
position = 5
|
||||
)
|
||||
default boolean showBossActivity()
|
||||
{
|
||||
@@ -98,7 +109,7 @@ public interface DiscordConfig extends Config
|
||||
keyName = "showCityActivity",
|
||||
name = "Cities",
|
||||
description = "Show your activity and location while in cities",
|
||||
position = 5
|
||||
position = 6
|
||||
)
|
||||
default boolean showCityActivity()
|
||||
{
|
||||
@@ -109,7 +120,7 @@ public interface DiscordConfig extends Config
|
||||
keyName = "showDungeonActivity",
|
||||
name = "Dungeons",
|
||||
description = "Show your activity and location while in dungeons",
|
||||
position = 6
|
||||
position = 7
|
||||
)
|
||||
default boolean showDungeonActivity()
|
||||
{
|
||||
@@ -120,7 +131,7 @@ public interface DiscordConfig extends Config
|
||||
keyName = "showMinigameActivity",
|
||||
name = "Minigames",
|
||||
description = "Show your activity and location while in minigames",
|
||||
position = 7
|
||||
position = 8
|
||||
)
|
||||
default boolean showMinigameActivity()
|
||||
{
|
||||
@@ -131,7 +142,7 @@ public interface DiscordConfig extends Config
|
||||
keyName = "showRaidingActivity",
|
||||
name = "Raids",
|
||||
description = "Show your activity and location while in Raids",
|
||||
position = 8
|
||||
position = 9
|
||||
)
|
||||
default boolean showRaidingActivity()
|
||||
{
|
||||
@@ -142,7 +153,7 @@ public interface DiscordConfig extends Config
|
||||
keyName = "showRegionsActivity",
|
||||
name = "Regions",
|
||||
description = "Show your activity and location while in other regions",
|
||||
position = 9
|
||||
position = 10
|
||||
)
|
||||
default boolean showRegionsActivity()
|
||||
{
|
||||
|
||||
@@ -358,10 +358,15 @@ public class DiscordPlugin extends Plugin
|
||||
|
||||
private void checkForGameStateUpdate()
|
||||
{
|
||||
discordState.triggerEvent(client.getGameState() == GameState.LOGGED_IN
|
||||
final boolean isLoggedIn = client.getGameState() == GameState.LOGGED_IN;
|
||||
|
||||
if (config.showMainMenu() || isLoggedIn)
|
||||
{
|
||||
discordState.triggerEvent(isLoggedIn
|
||||
? DiscordGameEventType.IN_GAME
|
||||
: DiscordGameEventType.IN_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForAreaUpdate()
|
||||
{
|
||||
|
||||
@@ -289,12 +289,18 @@ public class FriendsChatPlugin extends Plugin
|
||||
{
|
||||
chatTitleWidget.setText(TITLE + " (" + friendsChatManager.getCount() + "/100)");
|
||||
}
|
||||
else if (config.recentChats() && chatList.getChildren() == null && !Strings.isNullOrEmpty(owner.getText()))
|
||||
else if (chatList.getChildren() == null && !Strings.isNullOrEmpty(owner.getText()))
|
||||
{
|
||||
if (config.recentChats())
|
||||
{
|
||||
chatTitleWidget.setText(RECENT_TITLE);
|
||||
|
||||
loadFriendsChats();
|
||||
}
|
||||
else
|
||||
{
|
||||
chatTitleWidget.setText(TITLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.showJoinLeave())
|
||||
|
||||
@@ -31,9 +31,13 @@ import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("groundMarker")
|
||||
@ConfigGroup(GroundMarkerConfig.GROUND_MARKER_CONFIG_GROUP)
|
||||
public interface GroundMarkerConfig extends Config
|
||||
{
|
||||
String GROUND_MARKER_CONFIG_GROUP = "groundMarker";
|
||||
String SHOW_IMPORT_EXPORT_KEY_NAME = "showImportExport";
|
||||
String SHOW_CLEAR_KEY_NAME = "showClear";
|
||||
|
||||
@Alpha
|
||||
@ConfigItem(
|
||||
keyName = "markerColor",
|
||||
@@ -64,4 +68,24 @@ public interface GroundMarkerConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = SHOW_IMPORT_EXPORT_KEY_NAME,
|
||||
name = "Show Import/Export options",
|
||||
description = "Show the Import/Export options on the minimap right-click menu"
|
||||
)
|
||||
default boolean showImportExport()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = SHOW_CLEAR_KEY_NAME,
|
||||
name = "Show Clear option",
|
||||
description = "Show the Clear option on the minimap right-click menu, which deletes all currently loaded markers"
|
||||
)
|
||||
default boolean showClear()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
@@ -190,7 +191,14 @@ public class GroundMarkerPlugin extends Plugin
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(minimapOverlay);
|
||||
sharingManager.addMenuOptions();
|
||||
if (config.showImportExport())
|
||||
{
|
||||
sharingManager.addImportExportMenuOptions();
|
||||
}
|
||||
if (config.showClear())
|
||||
{
|
||||
sharingManager.addClearMenuOption();
|
||||
}
|
||||
loadPoints();
|
||||
eventBus.register(sharingManager);
|
||||
}
|
||||
@@ -280,6 +288,27 @@ public class GroundMarkerPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals(GroundMarkerConfig.GROUND_MARKER_CONFIG_GROUP)
|
||||
&& (event.getKey().equals(GroundMarkerConfig.SHOW_IMPORT_EXPORT_KEY_NAME)
|
||||
|| event.getKey().equals(GroundMarkerConfig.SHOW_CLEAR_KEY_NAME)))
|
||||
{
|
||||
// Maintain consistent menu option order by removing everything then adding according to config
|
||||
sharingManager.removeMenuOptions();
|
||||
|
||||
if (config.showImportExport())
|
||||
{
|
||||
sharingManager.addImportExportMenuOptions();
|
||||
}
|
||||
if (config.showClear())
|
||||
{
|
||||
sharingManager.addClearMenuOption();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void markTile(LocalPoint localPoint)
|
||||
{
|
||||
if (localPoint == null)
|
||||
|
||||
@@ -59,6 +59,7 @@ class GroundMarkerSharingManager
|
||||
{
|
||||
private static final WidgetMenuOption EXPORT_MARKERS_OPTION = new WidgetMenuOption("Export", "Ground Markers", WORLD_MAP_OPTION);
|
||||
private static final WidgetMenuOption IMPORT_MARKERS_OPTION = new WidgetMenuOption("Import", "Ground Markers", WORLD_MAP_OPTION);
|
||||
private static final WidgetMenuOption CLEAR_MARKERS_OPTION = new WidgetMenuOption("Clear", "Ground Markers", WORLD_MAP_OPTION);
|
||||
|
||||
private final GroundMarkerPlugin plugin;
|
||||
private final Client client;
|
||||
@@ -79,16 +80,22 @@ class GroundMarkerSharingManager
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
void addMenuOptions()
|
||||
void addImportExportMenuOptions()
|
||||
{
|
||||
menuManager.addManagedCustomMenu(EXPORT_MARKERS_OPTION);
|
||||
menuManager.addManagedCustomMenu(IMPORT_MARKERS_OPTION);
|
||||
}
|
||||
|
||||
void addClearMenuOption()
|
||||
{
|
||||
menuManager.addManagedCustomMenu(CLEAR_MARKERS_OPTION);
|
||||
}
|
||||
|
||||
void removeMenuOptions()
|
||||
{
|
||||
menuManager.removeManagedCustomMenu(EXPORT_MARKERS_OPTION);
|
||||
menuManager.removeManagedCustomMenu(IMPORT_MARKERS_OPTION);
|
||||
menuManager.removeManagedCustomMenu(CLEAR_MARKERS_OPTION);
|
||||
}
|
||||
|
||||
private boolean widgetMenuClickedEquals(final WidgetMenuOptionClicked event, final WidgetMenuOption target)
|
||||
@@ -114,6 +121,10 @@ class GroundMarkerSharingManager
|
||||
{
|
||||
promptForImport();
|
||||
}
|
||||
else if (widgetMenuClickedEquals(event, CLEAR_MARKERS_OPTION))
|
||||
{
|
||||
promptForClear();
|
||||
}
|
||||
}
|
||||
|
||||
private void exportGroundMarkers()
|
||||
@@ -233,6 +244,41 @@ class GroundMarkerSharingManager
|
||||
sendChatMessage(importPoints.size() + " ground markers were imported from the clipboard.");
|
||||
}
|
||||
|
||||
private void promptForClear()
|
||||
{
|
||||
int[] regions = client.getMapRegions();
|
||||
if (regions == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long numActivePoints = Arrays.stream(regions)
|
||||
.mapToLong(regionId -> plugin.getPoints(regionId).size())
|
||||
.sum();
|
||||
|
||||
if (numActivePoints == 0)
|
||||
{
|
||||
sendChatMessage("You have no ground markers to clear.");
|
||||
return;
|
||||
}
|
||||
|
||||
chatboxPanelManager.openTextMenuInput("Are you sure you want to clear the<br>" + numActivePoints + " currently loaded ground markers?")
|
||||
.option("Yes", () ->
|
||||
{
|
||||
for (int regionId : regions)
|
||||
{
|
||||
plugin.savePoints(regionId, null);
|
||||
}
|
||||
|
||||
plugin.loadPoints();
|
||||
sendChatMessage(numActivePoints + " ground marker"
|
||||
+ (numActivePoints == 1 ? " was cleared." : "s were cleared."));
|
||||
|
||||
})
|
||||
.option("No", Runnables::doNothing)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void sendChatMessage(final String message)
|
||||
{
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
|
||||
@@ -34,6 +34,7 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@PluginDescriptor(
|
||||
name = "Item Identification",
|
||||
description = "Show identifying text over items with difficult to distinguish sprites",
|
||||
tags = {"abbreviations", "labels", "seeds", "herbs", "saplings", "seedlings"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class ItemIdentificationPlugin extends Plugin
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Brandt Hill <https://github.com/BrandtHill>
|
||||
* 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.kingdomofmiscellania;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Range;
|
||||
|
||||
@ConfigGroup(KingdomConfig.CONFIG_GROUP_NAME)
|
||||
public interface KingdomConfig extends Config
|
||||
{
|
||||
String CONFIG_GROUP_NAME = "kingdomofmiscellania";
|
||||
int MAX_COFFER = 7_500_000;
|
||||
int MAX_APPROVAL_PERCENT = 100;
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "sendNotifications",
|
||||
name = "Send Notifications",
|
||||
description = "Send chat notifications upon login showing current estimated coffer and approval"
|
||||
)
|
||||
default boolean shouldSendNotifications()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Range(
|
||||
max = MAX_COFFER
|
||||
)
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "cofferThreshold",
|
||||
name = "Coffer Threshold",
|
||||
description = "Send notifications if coffer is below this value"
|
||||
)
|
||||
default int getCofferThreshold()
|
||||
{
|
||||
return MAX_COFFER;
|
||||
}
|
||||
|
||||
@Range(
|
||||
max = MAX_APPROVAL_PERCENT
|
||||
)
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "approvalThreshold",
|
||||
name = "Approval Threshold",
|
||||
description = "Send notifications if approval percentage is below this value"
|
||||
)
|
||||
default int getApprovalThreshold()
|
||||
{
|
||||
return MAX_APPROVAL_PERCENT;
|
||||
}
|
||||
}
|
||||
@@ -34,20 +34,20 @@ public class KingdomCounter extends Counter
|
||||
|
||||
KingdomCounter(BufferedImage image, KingdomPlugin plugin)
|
||||
{
|
||||
super(image, plugin, plugin.getFavor());
|
||||
super(image, plugin, plugin.getApproval());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
return KingdomPlugin.getFavorPercent(plugin.getFavor()) + "%";
|
||||
return KingdomPlugin.getApprovalPercent(plugin.getApproval()) + "%";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip()
|
||||
{
|
||||
return "Favor: " + plugin.getFavor() + "/127" + "</br>"
|
||||
return "Approval: " + plugin.getApproval() + "/" + KingdomPlugin.MAX_APPROVAL + "</br>"
|
||||
+ "Coffer: " + QuantityFormatter.quantityToStackSize(plugin.getCoffer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,32 +25,55 @@
|
||||
package net.runelite.client.plugins.kingdomofmiscellania;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Provides;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import static net.runelite.api.ItemID.TEAK_CHEST;
|
||||
import net.runelite.api.Quest;
|
||||
import net.runelite.api.QuestState;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.util.QuantityFormatter;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Kingdom of Miscellania",
|
||||
description = "Show amount of favor when inside Miscellania",
|
||||
tags = {"favor", "favour", "managing", "overlay"},
|
||||
description = "Show amount of approval when inside Miscellania",
|
||||
tags = {"favor", "favour", "managing", "overlay", "approval", "coffer"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
@Slf4j
|
||||
public class KingdomPlugin extends Plugin
|
||||
{
|
||||
private static final ImmutableSet<Integer> KINGDOM_REGION = ImmutableSet.of(10044, 10300);
|
||||
private static final String CONFIG_LAST_CHANGED_KEY = "lastChanged";
|
||||
private static final String CONFIG_COFFER_KEY = "coffer";
|
||||
private static final String CONFIG_APPROVAL_KEY = "approval";
|
||||
private static final String CHAT_MESSAGE_FORMAT = "Your Kingdom of Miscellania approval is %d%%, and your coffer has %s coins.";
|
||||
private static final int MAX_WITHDRAWAL_BASE = 50_000;
|
||||
private static final int MAX_WITHDRAWAL_ROYAL_TROUBLE = 75_000;
|
||||
private static final float APPROVAL_DECREMENT_BASE = 0.025f;
|
||||
private static final float APPROVAL_DECREMENT_ROYAL_TROUBLE = 0.010f;
|
||||
static final int MAX_APPROVAL = 127;
|
||||
|
||||
private boolean loggingIn;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@@ -61,8 +84,14 @@ public class KingdomPlugin extends Plugin
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Getter
|
||||
private int favor = 0, coffer = 0;
|
||||
@Inject
|
||||
private KingdomConfig config;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private ChatMessageManager chatMessageManager;
|
||||
|
||||
private KingdomCounter counter;
|
||||
|
||||
@@ -72,11 +101,28 @@ public class KingdomPlugin extends Plugin
|
||||
removeKingdomInfobox();
|
||||
}
|
||||
|
||||
@Provides
|
||||
KingdomConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(KingdomConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
favor = client.getVar(Varbits.KINGDOM_FAVOR);
|
||||
coffer = client.getVar(Varbits.KINGDOM_COFFER);
|
||||
final int coffer = client.getVar(Varbits.KINGDOM_COFFER);
|
||||
final int approval = client.getVar(Varbits.KINGDOM_APPROVAL);
|
||||
|
||||
if (client.getGameState() == GameState.LOGGED_IN
|
||||
&& isThroneOfMiscellaniaCompleted()
|
||||
&& (isInKingdom() || coffer > 0 && approval > 0)
|
||||
&& (getCoffer() != coffer || getApproval() != approval))
|
||||
{
|
||||
setLastChanged(Instant.now());
|
||||
setCoffer(coffer);
|
||||
setApproval(approval);
|
||||
}
|
||||
|
||||
processInfobox();
|
||||
}
|
||||
|
||||
@@ -87,11 +133,25 @@ public class KingdomPlugin extends Plugin
|
||||
{
|
||||
processInfobox();
|
||||
}
|
||||
else if (event.getGameState() == GameState.LOGGING_IN)
|
||||
{
|
||||
loggingIn = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick gameTick)
|
||||
{
|
||||
if (loggingIn)
|
||||
{
|
||||
loggingIn = false;
|
||||
createNotification();
|
||||
}
|
||||
}
|
||||
|
||||
private void processInfobox()
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN && hasCompletedQuest() && isInKingdom())
|
||||
if (client.getGameState() == GameState.LOGGED_IN && isThroneOfMiscellaniaCompleted() && isInKingdom())
|
||||
{
|
||||
addKingdomInfobox();
|
||||
}
|
||||
@@ -99,7 +159,33 @@ public class KingdomPlugin extends Plugin
|
||||
{
|
||||
removeKingdomInfobox();
|
||||
}
|
||||
}
|
||||
|
||||
private void createNotification()
|
||||
{
|
||||
if (!config.shouldSendNotifications() || !isThroneOfMiscellaniaCompleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (getLastChanged() == null)
|
||||
{
|
||||
log.debug("Kingdom Of Miscellania values not yet set. Visit Miscellania to automatically set values.");
|
||||
return;
|
||||
}
|
||||
|
||||
Instant lastChanged = getLastChanged();
|
||||
int lastCoffer = getCoffer();
|
||||
int lastApproval = getApproval();
|
||||
int estimatedCoffer = estimateCoffer(lastChanged, lastCoffer);
|
||||
int estimatedApproval = estimateApproval(lastChanged, lastApproval);
|
||||
if (estimatedCoffer < config.getCofferThreshold() || getApprovalPercent(estimatedApproval) < config.getApprovalThreshold())
|
||||
{
|
||||
sendChatMessage(String.format(
|
||||
CHAT_MESSAGE_FORMAT,
|
||||
getApprovalPercent(estimatedApproval),
|
||||
QuantityFormatter.quantityToStackSize(estimatedCoffer)));
|
||||
}
|
||||
}
|
||||
|
||||
private void addKingdomInfobox()
|
||||
@@ -122,20 +208,92 @@ public class KingdomPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private int estimateCoffer(Instant lastChanged, int lastCoffer)
|
||||
{
|
||||
int daysSince = (int) Duration.between(lastChanged, Instant.now()).toDays();
|
||||
int maxDailyWithdrawal = isRoyalTroubleCompleted() ? MAX_WITHDRAWAL_ROYAL_TROUBLE : MAX_WITHDRAWAL_BASE;
|
||||
int maxDailyThreshold = maxDailyWithdrawal * 10;
|
||||
|
||||
for (int i = 0; i < daysSince; i++)
|
||||
{
|
||||
lastCoffer -= (lastCoffer > maxDailyThreshold) ? maxDailyWithdrawal : lastCoffer / 10;
|
||||
}
|
||||
return lastCoffer;
|
||||
}
|
||||
|
||||
private int estimateApproval(Instant lastChanged, int lastApproval)
|
||||
{
|
||||
int daysSince = (int) Duration.between(lastChanged, Instant.now()).toDays();
|
||||
float dailyPercentage = isRoyalTroubleCompleted() ? APPROVAL_DECREMENT_ROYAL_TROUBLE : APPROVAL_DECREMENT_BASE;
|
||||
|
||||
lastApproval -= (int) (daysSince * dailyPercentage * MAX_APPROVAL);
|
||||
return Math.max(lastApproval, 0);
|
||||
}
|
||||
|
||||
private boolean isInKingdom()
|
||||
{
|
||||
return client.getLocalPlayer() != null
|
||||
&& KINGDOM_REGION.contains(client.getLocalPlayer().getWorldLocation().getRegionID());
|
||||
}
|
||||
|
||||
private boolean hasCompletedQuest()
|
||||
private boolean isThroneOfMiscellaniaCompleted()
|
||||
{
|
||||
return client.getVar(VarPlayer.THRONE_OF_MISCELLANIA) > 0;
|
||||
}
|
||||
|
||||
static int getFavorPercent(int favor)
|
||||
private boolean isRoyalTroubleCompleted()
|
||||
{
|
||||
return (favor * 100) / 127;
|
||||
return Quest.ROYAL_TROUBLE.getState(client) == QuestState.FINISHED;
|
||||
}
|
||||
|
||||
static int getApprovalPercent(int approval)
|
||||
{
|
||||
return (approval * 100) / MAX_APPROVAL;
|
||||
}
|
||||
|
||||
private void sendChatMessage(String chatMessage)
|
||||
{
|
||||
final String message = new ChatMessageBuilder()
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append(chatMessage)
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(
|
||||
QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(message)
|
||||
.build());
|
||||
}
|
||||
|
||||
private Instant getLastChanged()
|
||||
{
|
||||
return configManager.getRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_LAST_CHANGED_KEY, Instant.class);
|
||||
}
|
||||
|
||||
private void setLastChanged(Instant lastChanged)
|
||||
{
|
||||
configManager.setRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_LAST_CHANGED_KEY, lastChanged);
|
||||
}
|
||||
|
||||
int getCoffer()
|
||||
{
|
||||
Integer coffer = configManager.getRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_COFFER_KEY, int.class);
|
||||
return coffer == null ? 0 : coffer;
|
||||
}
|
||||
|
||||
private void setCoffer(int coffer)
|
||||
{
|
||||
configManager.setRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_COFFER_KEY, coffer);
|
||||
}
|
||||
|
||||
int getApproval()
|
||||
{
|
||||
Integer approval = configManager.getRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_APPROVAL_KEY, int.class);
|
||||
return approval == null ? 0 : approval;
|
||||
}
|
||||
|
||||
private void setApproval(int approval)
|
||||
{
|
||||
configManager.setRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_APPROVAL_KEY, approval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,13 +557,18 @@ public class MusicPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
for (Widget w : track.getChildren())
|
||||
Widget[] trackChildren = track.getChildren();
|
||||
|
||||
if (trackChildren != null)
|
||||
{
|
||||
for (Widget w : trackChildren)
|
||||
{
|
||||
if (w != null)
|
||||
{
|
||||
w.setAction(0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle.setOnVarTransmitListener((Object[]) null);
|
||||
handle.setDragParent(track);
|
||||
@@ -588,7 +593,11 @@ public class MusicPlugin extends Plugin
|
||||
public void shutDown()
|
||||
{
|
||||
super.shutDown();
|
||||
|
||||
if (this.handle != null)
|
||||
{
|
||||
handle.setSpriteId(SpriteID.SETTINGS_SLIDER_HANDLE_BLUE);
|
||||
}
|
||||
|
||||
this.icon.setOnOpListener((Object[]) null);
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.GraphicsObjectCreated;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NpcChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
@@ -409,6 +410,26 @@ public class NpcIndicatorsPlugin extends Plugin
|
||||
highlightedNpcs.remove(npc);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcChanged(NpcChanged event)
|
||||
{
|
||||
final NPC npc = event.getNpc();
|
||||
final String npcName = npc.getName();
|
||||
|
||||
highlightedNpcs.remove(npc);
|
||||
|
||||
if (npcName == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (npcTags.contains(npc.getIndex())
|
||||
|| highlightMatchesNPCName(npcName))
|
||||
{
|
||||
highlightedNpcs.add(npc);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGraphicsObjectCreated(GraphicsObjectCreated event)
|
||||
{
|
||||
|
||||
@@ -32,9 +32,21 @@ import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Units;
|
||||
|
||||
@ConfigGroup("slayer")
|
||||
@ConfigGroup(SlayerConfig.GROUP_NAME)
|
||||
public interface SlayerConfig extends Config
|
||||
{
|
||||
String GROUP_NAME = "slayer";
|
||||
|
||||
// Key names for stored task values
|
||||
String TASK_NAME_KEY = "taskName";
|
||||
String AMOUNT_KEY = "amount";
|
||||
String INIT_AMOUNT_KEY = "initialAmount";
|
||||
String TASK_LOC_KEY = "taskLocation";
|
||||
String STREAK_KEY = "streak";
|
||||
String POINTS_KEY = "points";
|
||||
String EXPEDITIOUS_CHARGES_KEY = "expeditious";
|
||||
String SLAUGHTER_CHARGES_KEY = "slaughter";
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "infobox",
|
||||
@@ -124,148 +136,4 @@ public interface SlayerConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stored data
|
||||
@ConfigItem(
|
||||
keyName = "taskName",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default String taskName()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "taskName",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void taskName(String key);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "amount",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int amount()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "amount",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void amount(int amt);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "initialAmount",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int initialAmount()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ConfigItem(
|
||||
keyName = "initialAmount",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void initialAmount(int initialAmount);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "taskLocation",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default String taskLocation()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "taskLocation",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void taskLocation(String key);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "streak",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int streak()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "streak",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void streak(int streak);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "points",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int points()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "points",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void points(int points);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "expeditious",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int expeditious()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "expeditious",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void expeditious(int expeditious);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "slaughter",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int slaughter()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "slaughter",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void slaughter(int slaughter);
|
||||
}
|
||||
|
||||
@@ -139,6 +139,9 @@ public class SlayerPlugin extends Plugin
|
||||
@Inject
|
||||
private SlayerConfig config;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@@ -227,12 +230,17 @@ public class SlayerPlugin extends Plugin
|
||||
{
|
||||
cachedXp = client.getSkillExperience(SLAYER);
|
||||
|
||||
if (config.amount() != -1
|
||||
&& !config.taskName().isEmpty())
|
||||
migrateConfig();
|
||||
|
||||
if (getIntProfileConfig(SlayerConfig.AMOUNT_KEY) != -1
|
||||
&& !getStringProfileConfig(SlayerConfig.TASK_NAME_KEY).isEmpty())
|
||||
{
|
||||
setExpeditiousChargeCount(config.expeditious());
|
||||
setSlaughterChargeCount(config.slaughter());
|
||||
clientThread.invoke(() -> setTask(config.taskName(), config.amount(), config.initialAmount(), config.taskLocation(), false));
|
||||
setExpeditiousChargeCount(getIntProfileConfig(SlayerConfig.EXPEDITIOUS_CHARGES_KEY));
|
||||
setSlaughterChargeCount(getIntProfileConfig(SlayerConfig.SLAUGHTER_CHARGES_KEY));
|
||||
clientThread.invoke(() -> setTask(getStringProfileConfig(SlayerConfig.TASK_NAME_KEY),
|
||||
getIntProfileConfig(SlayerConfig.AMOUNT_KEY),
|
||||
getIntProfileConfig(SlayerConfig.INIT_AMOUNT_KEY),
|
||||
getStringProfileConfig(SlayerConfig.TASK_LOC_KEY), false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,27 +283,50 @@ public class SlayerPlugin extends Plugin
|
||||
taggedNpcs.clear();
|
||||
break;
|
||||
case LOGGED_IN:
|
||||
if (config.amount() != -1
|
||||
&& !config.taskName().isEmpty()
|
||||
migrateConfig();
|
||||
if (getIntProfileConfig(SlayerConfig.AMOUNT_KEY) != -1
|
||||
&& !getStringProfileConfig(SlayerConfig.TASK_NAME_KEY).isEmpty()
|
||||
&& loginFlag)
|
||||
{
|
||||
setExpeditiousChargeCount(config.expeditious());
|
||||
setSlaughterChargeCount(config.slaughter());
|
||||
setTask(config.taskName(), config.amount(), config.initialAmount(), config.taskLocation(), false);
|
||||
setExpeditiousChargeCount(getIntProfileConfig(SlayerConfig.EXPEDITIOUS_CHARGES_KEY));
|
||||
setSlaughterChargeCount(getIntProfileConfig(SlayerConfig.SLAUGHTER_CHARGES_KEY));
|
||||
setTask(getStringProfileConfig(SlayerConfig.TASK_NAME_KEY),
|
||||
getIntProfileConfig(SlayerConfig.AMOUNT_KEY),
|
||||
getIntProfileConfig(SlayerConfig.INIT_AMOUNT_KEY),
|
||||
getStringProfileConfig(SlayerConfig.TASK_LOC_KEY), false);
|
||||
loginFlag = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
int getIntProfileConfig(String key)
|
||||
{
|
||||
Integer value = configManager.getRSProfileConfiguration(SlayerConfig.GROUP_NAME, key, int.class);
|
||||
return value == null ? -1 : value;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String getStringProfileConfig(String key)
|
||||
{
|
||||
String value = configManager.getRSProfileConfiguration(SlayerConfig.GROUP_NAME, key, String.class);
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
private void setProfileConfig(String key, Object value)
|
||||
{
|
||||
configManager.setRSProfileConfiguration(SlayerConfig.GROUP_NAME, key, value);
|
||||
}
|
||||
|
||||
private void save()
|
||||
{
|
||||
config.amount(amount);
|
||||
config.initialAmount(initialAmount);
|
||||
config.taskName(taskName);
|
||||
config.taskLocation(taskLocation);
|
||||
config.expeditious(expeditiousChargeCount);
|
||||
config.slaughter(slaughterChargeCount);
|
||||
setProfileConfig(SlayerConfig.AMOUNT_KEY, amount);
|
||||
setProfileConfig(SlayerConfig.INIT_AMOUNT_KEY, initialAmount);
|
||||
setProfileConfig(SlayerConfig.TASK_NAME_KEY, taskName);
|
||||
setProfileConfig(SlayerConfig.TASK_LOC_KEY, taskLocation);
|
||||
setProfileConfig(SlayerConfig.EXPEDITIOUS_CHARGES_KEY, expeditiousChargeCount);
|
||||
setProfileConfig(SlayerConfig.SLAUGHTER_CHARGES_KEY, slaughterChargeCount);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -345,7 +376,7 @@ public class SlayerPlugin extends Plugin
|
||||
int amount = Integer.parseInt(mAssignBoss.group(2));
|
||||
setTask(mAssignBoss.group(1), amount, amount);
|
||||
int points = Integer.parseInt(mAssignBoss.group(3).replaceAll(",", ""));
|
||||
config.points(points);
|
||||
setProfileConfig(SlayerConfig.POINTS_KEY, points);
|
||||
}
|
||||
else if (mCurrent.find())
|
||||
{
|
||||
@@ -363,12 +394,12 @@ public class SlayerPlugin extends Plugin
|
||||
if (braceletText.contains("bracelet of slaughter"))
|
||||
{
|
||||
slaughterChargeCount = SLAUGHTER_CHARGE;
|
||||
config.slaughter(slaughterChargeCount);
|
||||
setProfileConfig(SlayerConfig.SLAUGHTER_CHARGES_KEY, slaughterChargeCount);
|
||||
}
|
||||
else if (braceletText.contains("expeditious bracelet"))
|
||||
{
|
||||
expeditiousChargeCount = EXPEDITIOUS_CHARGE;
|
||||
config.expeditious(expeditiousChargeCount);
|
||||
setProfileConfig(SlayerConfig.EXPEDITIOUS_CHARGES_KEY, expeditiousChargeCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,12 +411,12 @@ public class SlayerPlugin extends Plugin
|
||||
Matcher mPoints = REWARD_POINTS.matcher(w.getText());
|
||||
if (mPoints.find())
|
||||
{
|
||||
final int prevPoints = config.points();
|
||||
final int prevPoints = getIntProfileConfig(SlayerConfig.POINTS_KEY);
|
||||
int points = Integer.parseInt(mPoints.group(1).replaceAll(",", ""));
|
||||
|
||||
if (prevPoints != points)
|
||||
{
|
||||
config.points(points);
|
||||
setProfileConfig(SlayerConfig.POINTS_KEY, points);
|
||||
removeCounter();
|
||||
addCounter();
|
||||
}
|
||||
@@ -426,7 +457,7 @@ public class SlayerPlugin extends Plugin
|
||||
|
||||
amount++;
|
||||
slaughterChargeCount = mSlaughter.find() ? Integer.parseInt(mSlaughter.group(1)) : SLAUGHTER_CHARGE;
|
||||
config.slaughter(slaughterChargeCount);
|
||||
setProfileConfig(SlayerConfig.SLAUGHTER_CHARGES_KEY, slaughterChargeCount);
|
||||
}
|
||||
|
||||
if (chatMsg.startsWith(CHAT_BRACELET_EXPEDITIOUS))
|
||||
@@ -435,7 +466,7 @@ public class SlayerPlugin extends Plugin
|
||||
|
||||
amount--;
|
||||
expeditiousChargeCount = mExpeditious.find() ? Integer.parseInt(mExpeditious.group(1)) : EXPEDITIOUS_CHARGE;
|
||||
config.expeditious(expeditiousChargeCount);
|
||||
setProfileConfig(SlayerConfig.EXPEDITIOUS_CHARGES_KEY, expeditiousChargeCount);
|
||||
}
|
||||
|
||||
if (chatMsg.startsWith(CHAT_BRACELET_EXPEDITIOUS_CHARGE))
|
||||
@@ -448,7 +479,7 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
|
||||
expeditiousChargeCount = Integer.parseInt(mExpeditious.group(1));
|
||||
config.expeditious(expeditiousChargeCount);
|
||||
setProfileConfig(SlayerConfig.EXPEDITIOUS_CHARGES_KEY, expeditiousChargeCount);
|
||||
}
|
||||
|
||||
if (chatMsg.startsWith(CHAT_BRACELET_SLAUGHTER_CHARGE))
|
||||
@@ -460,7 +491,7 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
|
||||
slaughterChargeCount = Integer.parseInt(mSlaughter.group(1));
|
||||
config.slaughter(slaughterChargeCount);
|
||||
setProfileConfig(SlayerConfig.SLAUGHTER_CHARGES_KEY, slaughterChargeCount);
|
||||
}
|
||||
|
||||
if (chatMsg.startsWith("You've completed") && (chatMsg.contains("Slayer master") || chatMsg.contains("Slayer Master")))
|
||||
@@ -479,12 +510,12 @@ public class SlayerPlugin extends Plugin
|
||||
if (mTasks != null)
|
||||
{
|
||||
int streak = Integer.parseInt(mTasks.replace(",", ""));
|
||||
config.streak(streak);
|
||||
setProfileConfig(SlayerConfig.STREAK_KEY, streak);
|
||||
}
|
||||
if (mPoints != null)
|
||||
{
|
||||
int points = Integer.parseInt(mPoints.replace(",", ""));
|
||||
config.points(points);
|
||||
setProfileConfig(SlayerConfig.POINTS_KEY, points);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +628,7 @@ public class SlayerPlugin extends Plugin
|
||||
@Subscribe
|
||||
private void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!event.getGroup().equals("slayer") || !event.getKey().equals("infobox"))
|
||||
if (!event.getGroup().equals(SlayerConfig.GROUP_NAME) || !event.getKey().equals("infobox"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -627,7 +658,8 @@ public class SlayerPlugin extends Plugin
|
||||
amount--;
|
||||
}
|
||||
|
||||
config.amount(amount); // save changed value
|
||||
// save changed value
|
||||
setProfileConfig(SlayerConfig.AMOUNT_KEY, amount);
|
||||
|
||||
if (!config.showInfobox())
|
||||
{
|
||||
@@ -772,7 +804,7 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
|
||||
counter = new TaskCounter(taskImg, this, amount);
|
||||
counter.setTooltip(String.format(taskTooltip, capsString(taskName), config.points(), config.streak()));
|
||||
counter.setTooltip(String.format(taskTooltip, capsString(taskName), getIntProfileConfig(SlayerConfig.POINTS_KEY), getIntProfileConfig(SlayerConfig.STREAK_KEY)));
|
||||
|
||||
infoBoxManager.addInfoBox(counter);
|
||||
}
|
||||
@@ -891,4 +923,26 @@ public class SlayerPlugin extends Plugin
|
||||
{
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
}
|
||||
|
||||
private void migrateConfig()
|
||||
{
|
||||
migrateConfigKey(SlayerConfig.TASK_NAME_KEY);
|
||||
migrateConfigKey(SlayerConfig.AMOUNT_KEY);
|
||||
migrateConfigKey(SlayerConfig.INIT_AMOUNT_KEY);
|
||||
migrateConfigKey(SlayerConfig.TASK_LOC_KEY);
|
||||
migrateConfigKey(SlayerConfig.STREAK_KEY);
|
||||
migrateConfigKey(SlayerConfig.POINTS_KEY);
|
||||
migrateConfigKey(SlayerConfig.EXPEDITIOUS_CHARGES_KEY);
|
||||
migrateConfigKey(SlayerConfig.SLAUGHTER_CHARGES_KEY);
|
||||
}
|
||||
|
||||
private void migrateConfigKey(String key)
|
||||
{
|
||||
Object value = configManager.getConfiguration(SlayerConfig.GROUP_NAME, key);
|
||||
if (value != null)
|
||||
{
|
||||
configManager.unsetConfiguration(SlayerConfig.GROUP_NAME, key);
|
||||
configManager.setRSProfileConfiguration(SlayerConfig.GROUP_NAME, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,10 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
@@ -286,4 +289,46 @@ public class ChatNotificationsPluginTest
|
||||
// set value uses our player name, which has nbsp replaced
|
||||
verify(messageNode).setValue("<col=005f00><colHIGHLIGHT><u>Logic Knot</u><col=005f00> received a drop: Adamant longsword</col>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalPlayerSelfMention()
|
||||
{
|
||||
final String localPlayerName = "Broo klyn";
|
||||
|
||||
MessageNode messageNode = mock(MessageNode.class);
|
||||
|
||||
Player localPlayer = mock(Player.class);
|
||||
when(client.getLocalPlayer()).thenReturn(localPlayer);
|
||||
when(localPlayer.getName()).thenReturn(localPlayerName);
|
||||
|
||||
lenient().when(config.highlightOwnName()).thenReturn(true);
|
||||
lenient().when(messageNode.getValue()).thenReturn("Spread love it's the Broo klyn way");
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.PUBLICCHAT);
|
||||
chatMessage.setName("Broo\u00a0klyn");
|
||||
chatMessage.setMessageNode(messageNode);
|
||||
|
||||
chatNotificationsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(messageNode, times(0)).setValue(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrivateChatOutReturn()
|
||||
{
|
||||
MessageNode messageNode = mock(MessageNode.class);
|
||||
|
||||
lenient().when(config.highlightWordsString()).thenReturn("Brooklyn");
|
||||
lenient().when(messageNode.getValue()).thenReturn("Spread love it's the Brooklyn way");
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.setType(ChatMessageType.PRIVATECHATOUT);
|
||||
chatMessage.setMessageNode(messageNode);
|
||||
|
||||
chatNotificationsPlugin.startUp();
|
||||
chatNotificationsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(messageNode, times(0)).setValue(any());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 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.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.ArgumentMatchers.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.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CookingPluginTest
|
||||
{
|
||||
private static final String[] COOKING_MESSAGES = {
|
||||
"You successfully cook a shark.",
|
||||
"You successfully cook an anglerfish.",
|
||||
"You manage to cook a tuna.",
|
||||
"You cook the karambwan. It looks delicious.",
|
||||
"You roast a lobster.",
|
||||
"You cook a bass.",
|
||||
"You successfully bake a tasty garden pie.",
|
||||
"You dry a piece of meat and extract the sinew."
|
||||
};
|
||||
|
||||
private static final String incenseBurnerMessage = "You burn some marrentill in the incense burner.";
|
||||
|
||||
@Inject
|
||||
CookingPlugin cookingPlugin;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
Client client;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
InfoBoxManager infoBoxManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
ItemManager itemManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
CookingConfig config;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
CookingOverlay cookingOverlay;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
OverlayManager overlayManager;
|
||||
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnChatMessage()
|
||||
{
|
||||
for (String message : COOKING_MESSAGES)
|
||||
{
|
||||
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", message, "", 0);
|
||||
cookingPlugin.onChatMessage(chatMessage);
|
||||
}
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", incenseBurnerMessage, "", 0);
|
||||
cookingPlugin.onChatMessage(chatMessage);
|
||||
|
||||
CookingSession cookingSession = cookingPlugin.getSession();
|
||||
assertNotNull(cookingSession);
|
||||
assertEquals(COOKING_MESSAGES.length, cookingSession.getCookAmount());
|
||||
assertEquals(0, cookingSession.getBurnAmount());
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.npchighlight;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.testing.fieldbinder.Bind;
|
||||
import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
||||
import java.awt.Color;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.NpcChanged;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
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 NpcIndicatorsPluginTest
|
||||
{
|
||||
@Mock
|
||||
@Bind
|
||||
private Client client;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private NpcIndicatorsConfig npcIndicatorsConfig;
|
||||
|
||||
@Inject
|
||||
private NpcIndicatorsPlugin npcIndicatorsPlugin;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getHighlights()
|
||||
{
|
||||
when(npcIndicatorsConfig.getNpcToHighlight()).thenReturn("goblin, , zulrah , *wyvern, ,");
|
||||
final List<String> highlightedNpcs = npcIndicatorsPlugin.getHighlights();
|
||||
assertEquals("Length of parsed NPCs is incorrect", 3, highlightedNpcs.size());
|
||||
|
||||
final Iterator<String> iterator = highlightedNpcs.iterator();
|
||||
assertEquals("goblin", iterator.next());
|
||||
assertEquals("zulrah", iterator.next());
|
||||
assertEquals("*wyvern", iterator.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDeadNpcMenuHighlight()
|
||||
{
|
||||
when(npcIndicatorsConfig.getNpcToHighlight()).thenReturn("goblin");
|
||||
when(npcIndicatorsConfig.deadNpcMenuColor()).thenReturn(Color.RED);
|
||||
|
||||
npcIndicatorsPlugin.rebuildAllNpcs();
|
||||
|
||||
NPC npc = mock(NPC.class);
|
||||
when(npc.getName()).thenReturn("Goblin");
|
||||
when(npc.isDead()).thenReturn(true);
|
||||
npcIndicatorsPlugin.onNpcSpawned(new NpcSpawned(npc));
|
||||
|
||||
when(client.getCachedNPCs()).thenReturn(new NPC[]{npc}); // id 0
|
||||
|
||||
when(client.getMenuEntries()).thenReturn(new MenuEntry[]{new MenuEntry()});
|
||||
MenuEntryAdded menuEntryAdded = new MenuEntryAdded("", "Goblin", MenuAction.NPC_FIRST_OPTION.getId(), 0, -1, -1, false);
|
||||
npcIndicatorsPlugin.onMenuEntryAdded(menuEntryAdded);
|
||||
|
||||
MenuEntry target = new MenuEntry();
|
||||
target.setTarget("<col=ff0000>Goblin"); // red
|
||||
verify(client).setMenuEntries(new MenuEntry[]{target});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testAliveNpcMenuHighlight()
|
||||
{
|
||||
when(npcIndicatorsConfig.getNpcToHighlight()).thenReturn("goblin");
|
||||
when(npcIndicatorsConfig.highlightMenuNames()).thenReturn(true);
|
||||
when(npcIndicatorsConfig.getHighlightColor()).thenReturn(Color.BLUE);
|
||||
|
||||
npcIndicatorsPlugin.rebuildAllNpcs();
|
||||
|
||||
NPC npc = mock(NPC.class);
|
||||
when(npc.getName()).thenReturn("Goblin");
|
||||
npcIndicatorsPlugin.onNpcSpawned(new NpcSpawned(npc));
|
||||
|
||||
when(client.getCachedNPCs()).thenReturn(new NPC[]{npc}); // id 0
|
||||
|
||||
when(client.getMenuEntries()).thenReturn(new MenuEntry[]{new MenuEntry()});
|
||||
MenuEntryAdded menuEntryAdded = new MenuEntryAdded("", "Goblin", MenuAction.NPC_FIRST_OPTION.getId(), 0, -1, -1, false);
|
||||
npcIndicatorsPlugin.onMenuEntryAdded(menuEntryAdded);
|
||||
|
||||
MenuEntry target = new MenuEntry();
|
||||
target.setTarget("<col=0000ff>Goblin"); // blue
|
||||
verify(client).setMenuEntries(new MenuEntry[]{target});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taggedNpcChanges()
|
||||
{
|
||||
when(npcIndicatorsConfig.getNpcToHighlight()).thenReturn("Joseph");
|
||||
|
||||
npcIndicatorsPlugin.rebuildAllNpcs();
|
||||
|
||||
NPC npc = mock(NPC.class);
|
||||
when(npc.getName()).thenReturn("Joseph");
|
||||
npcIndicatorsPlugin.onNpcSpawned(new NpcSpawned(npc));
|
||||
|
||||
assertTrue(npcIndicatorsPlugin.getHighlightedNpcs().contains(npc));
|
||||
|
||||
when(npc.getName()).thenReturn("Werewolf");
|
||||
npcIndicatorsPlugin.onNpcChanged(new NpcChanged(npc, null));
|
||||
|
||||
assertFalse(npcIndicatorsPlugin.getHighlightedNpcs().contains(npc));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void npcChangesToTagged()
|
||||
{
|
||||
when(npcIndicatorsConfig.getNpcToHighlight()).thenReturn("Werewolf");
|
||||
|
||||
npcIndicatorsPlugin.rebuildAllNpcs();
|
||||
|
||||
NPC npc = mock(NPC.class);
|
||||
when(npc.getName()).thenReturn("Joseph");
|
||||
npcIndicatorsPlugin.onNpcSpawned(new NpcSpawned(npc));
|
||||
|
||||
assertFalse(npcIndicatorsPlugin.getHighlightedNpcs().contains(npc));
|
||||
|
||||
when(npc.getName()).thenReturn("Werewolf");
|
||||
npcIndicatorsPlugin.onNpcChanged(new NpcChanged(npc, null));
|
||||
|
||||
assertTrue(npcIndicatorsPlugin.getHighlightedNpcs().contains(npc));
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.chat.ChatCommandManager;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
@@ -64,6 +65,7 @@ import org.junit.runner.RunWith;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -137,6 +139,10 @@ public class SlayerPluginTest
|
||||
@Bind
|
||||
Client client;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
ConfigManager configManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
SlayerConfig slayerConfig;
|
||||
@@ -283,7 +289,7 @@ public class SlayerPluginTest
|
||||
|
||||
assertEquals("Vet'ion", slayerPlugin.getTaskName());
|
||||
assertEquals(3, slayerPlugin.getAmount());
|
||||
verify(slayerConfig).points(914);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 914);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -296,7 +302,7 @@ public class SlayerPluginTest
|
||||
|
||||
assertEquals("Chaos Elemental", slayerPlugin.getTaskName());
|
||||
assertEquals(3, slayerPlugin.getAmount());
|
||||
verify(slayerConfig).points(914);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 914);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -309,7 +315,7 @@ public class SlayerPluginTest
|
||||
|
||||
assertEquals("Alchemical Hydra", slayerPlugin.getTaskName());
|
||||
assertEquals(35, slayerPlugin.getAmount());
|
||||
verify(slayerConfig).points(724);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 724);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -440,7 +446,7 @@ public class SlayerPluginTest
|
||||
when(client.getWidget(WidgetInfo.SLAYER_REWARDS_TOPBAR)).thenReturn(rewardBar);
|
||||
slayerPlugin.onGameTick(new GameTick());
|
||||
|
||||
verify(slayerConfig).points(17566);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 17566);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -449,7 +455,7 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_ONE, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(1);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 1);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
}
|
||||
@@ -460,7 +466,7 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_COMPLETE_NO_POINTS, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(3);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 3);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
}
|
||||
@@ -471,10 +477,10 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_POINTS, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(9);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 9);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
verify(slayerConfig).points(18_000);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 18_000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -483,10 +489,10 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_LARGE_STREAK, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(2465);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 2465);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
verify(slayerConfig).points(131_071);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 131_071);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -495,7 +501,7 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_COMPETE_TURAEL, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(104);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 104);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
}
|
||||
@@ -506,8 +512,8 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_MAX_STREAK, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(16_000);
|
||||
verify(slayerConfig).points(131_071);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 16000);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 131_071);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
}
|
||||
@@ -518,8 +524,8 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_MAX_POINTS, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(9);
|
||||
verify(slayerConfig).points(131_071);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 9);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 131_071);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
}
|
||||
@@ -530,8 +536,8 @@ public class SlayerPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", TASK_WILDERNESS, null, 0);
|
||||
slayerPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(slayerConfig).streak(9);
|
||||
verify(slayerConfig).points(18_000);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.STREAK_KEY, 9);
|
||||
verify(configManager).setRSProfileConfiguration(SlayerConfig.GROUP_NAME, SlayerConfig.POINTS_KEY, 18_000);
|
||||
assertEquals("", slayerPlugin.getTaskName());
|
||||
assertEquals(0, slayerPlugin.getAmount());
|
||||
}
|
||||
@@ -919,7 +925,10 @@ public class SlayerPluginTest
|
||||
@Test
|
||||
public void infoboxNotAddedOnLogin()
|
||||
{
|
||||
when(slayerConfig.taskName()).thenReturn(Task.BLOODVELD.getName());
|
||||
when(slayerPlugin.getStringProfileConfig(SlayerConfig.TASK_NAME_KEY)).thenReturn(Task.BLOODVELD.getName());
|
||||
when(slayerPlugin.getIntProfileConfig(SlayerConfig.AMOUNT_KEY)).thenReturn(50);
|
||||
// Lenient required as this is not called assuming correct plugin logic
|
||||
lenient().when(slayerConfig.showInfobox()).thenReturn(true);
|
||||
|
||||
GameStateChanged loggingIn = new GameStateChanged();
|
||||
loggingIn.setGameState(GameState.LOGGING_IN);
|
||||
|
||||
38
runelite-jshell/runelite-jshell.gradle.kts
Normal file
38
runelite-jshell/runelite-jshell.gradle.kts
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
description = "RuneLite JShell"
|
||||
|
||||
dependencies {
|
||||
annotationProcessor(group = "org.projectlombok", name = "lombok", version = "1.18.4")
|
||||
|
||||
compileOnly(group = "org.projectlombok", name = "lombok", version = "1.18.4")
|
||||
|
||||
implementation(group = "com.google.code.findbugs", name = "jsr305", version = "3.0.2")
|
||||
implementation(group = "com.google.inject", name = "guice", version = "4.1.0", classifier = "no_aop")
|
||||
implementation(group = "com.fifesoft", name = "rsyntaxtextarea", version = "3.1.2")
|
||||
implementation(group = "com.fifesoft", name = "autocomplete", version = "3.1.1")
|
||||
implementation(group = "org.slf4j", name = "slf4j-api", version = "1.7.12")
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.jshell;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import jdk.jshell.JShell;
|
||||
import jdk.jshell.SourceCodeAnalysis;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.fife.ui.autocomplete.BasicCompletion;
|
||||
import org.fife.ui.autocomplete.Completion;
|
||||
import org.fife.ui.autocomplete.CompletionProviderBase;
|
||||
import org.fife.ui.autocomplete.ParameterizedCompletion;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class JShellAutocompleteProvider extends CompletionProviderBase
|
||||
{
|
||||
private final JShell shell;
|
||||
private String anchorText;
|
||||
private List<Completion> completions;
|
||||
|
||||
@Override
|
||||
protected List<Completion> getCompletionsImpl(JTextComponent comp)
|
||||
{
|
||||
return completions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlreadyEnteredText(JTextComponent comp)
|
||||
{
|
||||
complete(comp);
|
||||
return anchorText;
|
||||
}
|
||||
|
||||
private void complete(JTextComponent comp)
|
||||
{
|
||||
completions = Collections.emptyList();
|
||||
|
||||
String src = comp.getText();
|
||||
int cursor = comp.getCaretPosition();
|
||||
|
||||
for (int offset = 0; offset < src.length() && cursor >= offset; )
|
||||
{
|
||||
var snipSrc = src.substring(offset);
|
||||
int thisOffset = offset;
|
||||
var ci = shell.sourceCodeAnalysis().analyzeCompletion(snipSrc);
|
||||
offset = src.length() - ci.remaining().length();
|
||||
boolean mayHaveMore = ci.completeness() == SourceCodeAnalysis.Completeness.COMPLETE_WITH_SEMI
|
||||
|| ci.completeness() == SourceCodeAnalysis.Completeness.COMPLETE;
|
||||
|
||||
if (cursor <= offset || !mayHaveMore)
|
||||
{
|
||||
var anchor = new int[1];
|
||||
|
||||
completions = shell.sourceCodeAnalysis()
|
||||
.completionSuggestions(snipSrc, cursor - thisOffset, anchor)
|
||||
.stream()
|
||||
.filter(v -> !v.continuation().startsWith("$"))
|
||||
.map(s ->
|
||||
{
|
||||
return new BasicCompletion(this, s.continuation());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
anchorText = snipSrc.substring(anchor[0], cursor - thisOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (completions.isEmpty())
|
||||
{
|
||||
anchorText = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Completion> getCompletionsAt(JTextComponent comp, Point p)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoActivateOkay(JTextComponent comp)
|
||||
{
|
||||
// try not to start autocomplete when it has no useful context
|
||||
String text = comp.getText();
|
||||
for (int i = comp.getCaretPosition(); i >= 0; i--)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (Character.isJavaIdentifierPart(c) || c == '.' || c == '(')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Character.isWhitespace(c))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParameterizedCompletion> getParameterizedCompletions(JTextComponent tc)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.jshell;
|
||||
|
||||
import java.util.Map;
|
||||
import jdk.jshell.execution.DirectExecutionControl;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import jdk.jshell.spi.ExecutionControlProvider;
|
||||
import jdk.jshell.spi.ExecutionEnv;
|
||||
|
||||
public class RLShellExecutionControl extends DirectExecutionControl implements ExecutionControlProvider
|
||||
{
|
||||
public RLShellExecutionControl()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name()
|
||||
{
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionControl generate(ExecutionEnv env, Map<String, String> parameters) throws Throwable
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.jshell;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jshell.EvalException;
|
||||
|
||||
class RemappingThrowable extends Throwable
|
||||
{
|
||||
private final String source;
|
||||
private final Map<String, Integer> offsets;
|
||||
private final Throwable wrapped;
|
||||
private final Map<Throwable, Throwable> dejaVu;
|
||||
|
||||
public RemappingThrowable(String source, Map<String, Integer> offsets, Throwable other)
|
||||
{
|
||||
this(source, offsets, other, new HashMap<>());
|
||||
}
|
||||
|
||||
private RemappingThrowable(String source, Map<String, Integer> offsets, Throwable other, Map<Throwable, Throwable> dejaVu)
|
||||
{
|
||||
super();
|
||||
|
||||
this.source = source;
|
||||
this.offsets = offsets;
|
||||
this.wrapped = other;
|
||||
this.dejaVu = dejaVu;
|
||||
|
||||
dejaVu.put(wrapped, this);
|
||||
|
||||
setStackTrace(Stream.of(wrapped.getStackTrace())
|
||||
.map(e ->
|
||||
{
|
||||
Integer boxOffset = offsets.get(e.getFileName());
|
||||
if (boxOffset == null)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
int offset = boxOffset;
|
||||
int line = e.getLineNumber();
|
||||
for (int i = 0; i <= offset && i < source.length(); i++)
|
||||
{
|
||||
if (source.charAt(i) == '\n')
|
||||
{
|
||||
line++;
|
||||
}
|
||||
}
|
||||
return new StackTraceElement(
|
||||
Strings.isNullOrEmpty(e.getClassName()) ? "Shell" : e.getClassName(),
|
||||
Strings.isNullOrEmpty(e.getMethodName()) ? "global" : e.getMethodName(),
|
||||
"",
|
||||
line);
|
||||
})
|
||||
.toArray(StackTraceElement[]::new));
|
||||
|
||||
if (wrapped.getCause() != null)
|
||||
{
|
||||
initCause(remap(wrapped.getCause()));
|
||||
}
|
||||
|
||||
for (Throwable suppressed : wrapped.getSuppressed())
|
||||
{
|
||||
addSuppressed(remap(suppressed));
|
||||
}
|
||||
}
|
||||
|
||||
private Throwable remap(Throwable other)
|
||||
{
|
||||
Throwable remap = dejaVu.get(other);
|
||||
if (remap == null)
|
||||
{
|
||||
remap = new RemappingThrowable(source, offsets, other, dejaVu);
|
||||
// ctor inserts into the map
|
||||
}
|
||||
return remap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
return wrapped.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedMessage()
|
||||
{
|
||||
return wrapped.getLocalizedMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String className;
|
||||
if (wrapped instanceof EvalException)
|
||||
{
|
||||
className = ((EvalException) wrapped).getExceptionClassName();
|
||||
}
|
||||
else
|
||||
{
|
||||
className = wrapped.getClass().getName();
|
||||
}
|
||||
|
||||
String message = wrapped.getLocalizedMessage();
|
||||
if (message == null)
|
||||
{
|
||||
return className;
|
||||
}
|
||||
return className + ": " + message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.jshell;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Injector;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Font;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Segment;
|
||||
import jdk.jshell.Diag;
|
||||
import jdk.jshell.JShell;
|
||||
import jdk.jshell.Snippet;
|
||||
import jdk.jshell.SnippetEvent;
|
||||
import jdk.jshell.SourceCodeAnalysis;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.fife.ui.autocomplete.AutoCompletion;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
import org.fife.ui.rsyntaxtextarea.Theme;
|
||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Slf4j
|
||||
public abstract class ShellPanel extends JPanel
|
||||
{
|
||||
private final ScheduledExecutorService executor;
|
||||
|
||||
private final RSyntaxTextArea textArea;
|
||||
private final JTextArea console = new JTextArea();
|
||||
|
||||
@Getter
|
||||
private final Logger shellLogger;
|
||||
|
||||
private final List<Runnable> cleanup = new ArrayList<>();
|
||||
|
||||
private RLShellExecutionControl exec;
|
||||
private JShell shell;
|
||||
private Set<Snippet> prelude;
|
||||
private Injector injector;
|
||||
private AutoCompletion autoCompletion;
|
||||
|
||||
public static ShellPanel INSTANCE;
|
||||
|
||||
public ShellPanel(ScheduledExecutorService executor)
|
||||
{
|
||||
this.executor = executor;
|
||||
|
||||
Font codeFont = Stream.of(
|
||||
"Source code pro",
|
||||
"DejaVu Sans Code",
|
||||
"Consolas",
|
||||
Font.MONOSPACED)
|
||||
.map(name -> new Font(name, Font.PLAIN, 12))
|
||||
.filter(f -> !"Dialog.plain".equals(f.getFontName()))
|
||||
.findFirst()
|
||||
.get();
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JPanel topPanel = new JPanel();
|
||||
topPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
|
||||
JButton run = new JButton("⯈");
|
||||
run.setToolTipText("Run");
|
||||
run.addActionListener(ev -> run());
|
||||
topPanel.add(run);
|
||||
|
||||
JButton clear = new JButton("🗑");
|
||||
run.setToolTipText("Clear console");
|
||||
clear.addActionListener(ev -> console.setText(""));
|
||||
topPanel.add(clear);
|
||||
|
||||
add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
textArea = new RSyntaxTextArea();
|
||||
|
||||
try
|
||||
{
|
||||
// RSyntaxTextArea::setAntiAliasingEnabled actually forces it to match the platform's
|
||||
// default, which is pointless
|
||||
var map = new HashMap<RenderingHints.Key, Object>();
|
||||
map.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
var f = RSyntaxTextArea.class.getDeclaredField("aaHints");
|
||||
f.setAccessible(true);
|
||||
f.set(textArea, map);
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
textArea.setFont(codeFont);
|
||||
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
|
||||
textArea.setAutoIndentEnabled(true);
|
||||
textArea.setPaintTabLines(true);
|
||||
textArea.setShowMatchedBracketPopup(true);
|
||||
textArea.setCloseCurlyBraces(false);
|
||||
textArea.setTabSize(2);
|
||||
textArea.setMarkOccurrences(true);
|
||||
textArea.setMarkOccurrencesDelay(200);
|
||||
textArea.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (e.getKeyCode() == KeyEvent.VK_R && (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0)
|
||||
{
|
||||
run();
|
||||
e.consume();
|
||||
}
|
||||
if (e.getKeyCode() == KeyEvent.VK_F10)
|
||||
{
|
||||
run();
|
||||
e.consume();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var textScrollArea = new RTextScrollPane(textArea);
|
||||
|
||||
try
|
||||
{
|
||||
Theme.load(ShellPanel.class.getResourceAsStream("darcula.xml"), codeFont)
|
||||
.apply(textArea);
|
||||
|
||||
try (var is = ShellPanel.class.getResourceAsStream("default.jsh"))
|
||||
{
|
||||
textArea.setText(new String(is.readAllBytes(), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
console.setFont(codeFont);
|
||||
console.setFocusable(false);
|
||||
console.setEditable(false);
|
||||
console.setOpaque(false); // this turns off the hover effect for some reason
|
||||
|
||||
var split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textScrollArea, new JScrollPane(console));
|
||||
split.setResizeWeight(.8);
|
||||
split.setPreferredSize(new Dimension(800, 800));
|
||||
add(split, BorderLayout.CENTER);
|
||||
|
||||
shellLogger = new TeeLogger(LoggerFactory.getLogger("Shell"), this::logToConsole);
|
||||
INSTANCE = this;
|
||||
|
||||
// make sure jshell is on the classpath
|
||||
JShell.builder();
|
||||
}
|
||||
|
||||
public void switchContext(Injector injector)
|
||||
{
|
||||
freeContext();
|
||||
|
||||
this.injector = injector;
|
||||
|
||||
exec = new RLShellExecutionControl()
|
||||
{
|
||||
@Override
|
||||
protected String invoke(Method doitMethod) throws Exception
|
||||
{
|
||||
var result = new AtomicReference<>();
|
||||
var sema = new Semaphore(0);
|
||||
invokeOnClientThread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
result.set(super.invoke(doitMethod));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.set(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
sema.release();
|
||||
}
|
||||
});
|
||||
sema.acquire();
|
||||
if (result.get() instanceof String)
|
||||
{
|
||||
return (String) result.get();
|
||||
}
|
||||
throw (Exception) result.get();
|
||||
}
|
||||
};
|
||||
|
||||
shell = JShell.builder()
|
||||
.executionEngine(exec, null)
|
||||
.build();
|
||||
|
||||
String preludeStr;
|
||||
try (var is = ShellPanel.class.getResourceAsStream("prelude.jsh"))
|
||||
{
|
||||
preludeStr = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
prelude = ImmutableSet.copyOf(eval(preludeStr, false));
|
||||
|
||||
var cp = new JShellAutocompleteProvider(shell);
|
||||
autoCompletion = new AutoCompletion(cp);
|
||||
autoCompletion.setAutoActivationDelay(200);
|
||||
autoCompletion.setAutoActivationEnabled(true);
|
||||
autoCompletion.setAutoCompleteSingleChoices(false);
|
||||
autoCompletion.install(this.textArea);
|
||||
}
|
||||
|
||||
public void logToConsole(String message)
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = console.getDocument();
|
||||
if (doc.getLength() > 100_000)
|
||||
{
|
||||
Segment seg = new Segment();
|
||||
int i = doc.getLength() - 75_000;
|
||||
for (; i < doc.getLength(); i++)
|
||||
{
|
||||
doc.getText(i, 1, seg);
|
||||
if (seg.array[0] == '\n')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
doc.remove(0, i);
|
||||
}
|
||||
doc.insertString(doc.getLength(), message + "\n", null);
|
||||
console.setCaretPosition(doc.getLength());
|
||||
}
|
||||
catch (BadLocationException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<Snippet> eval(String src, boolean isUserCode)
|
||||
{
|
||||
var out = new ArrayList<Snippet>();
|
||||
var offsets = new HashMap<String, Integer>();
|
||||
String output = null;
|
||||
evaluation:
|
||||
for (int offset = 0; offset < src.length(); )
|
||||
{
|
||||
// Workaround a jdk bug
|
||||
for (; src.charAt(offset) == '\n'; offset++);
|
||||
|
||||
var ci = shell.sourceCodeAnalysis().analyzeCompletion(src.substring(offset));
|
||||
int thisOffset = offset;
|
||||
offset = src.length() - ci.remaining().length();
|
||||
if (ci.completeness() == SourceCodeAnalysis.Completeness.EMPTY)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
List<SnippetEvent> evs = shell.eval(ci.source());
|
||||
for (var ev : evs)
|
||||
{
|
||||
Snippet snip = ev.snippet();
|
||||
offsets.put("#" + snip.id(), thisOffset);
|
||||
if (ev.status() != Snippet.Status.VALID && ev.status() != Snippet.Status.RECOVERABLE_DEFINED)
|
||||
{
|
||||
var diags = shell.diagnostics(snip).collect(Collectors.toList());
|
||||
for (var diag : diags)
|
||||
{
|
||||
String msg = toStringDiagnostic(src, thisOffset, diag);
|
||||
if (isUserCode)
|
||||
{
|
||||
logToConsole(msg);
|
||||
// It might be nice to highlight stuff here
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("prelude error: " + msg);
|
||||
}
|
||||
}
|
||||
if (diags.isEmpty())
|
||||
{
|
||||
logToConsole("bad snippet" + ev.status());
|
||||
}
|
||||
break evaluation;
|
||||
}
|
||||
if (ev.exception() != null)
|
||||
{
|
||||
if (isUserCode)
|
||||
{
|
||||
shellLogger.error("", new RemappingThrowable(src, offsets, ev.exception()));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("prelude error", ev.exception());
|
||||
}
|
||||
}
|
||||
output = ev.value();
|
||||
|
||||
out.add(snip);
|
||||
}
|
||||
}
|
||||
|
||||
if (isUserCode && !Strings.isNullOrEmpty(output))
|
||||
{
|
||||
logToConsole("[OUTPUT] " + output);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private String toStringDiagnostic(String source, int offset, Diag diag)
|
||||
{
|
||||
int line = 1;
|
||||
int column = 1;
|
||||
offset += (int) diag.getPosition();
|
||||
for (int i = 0; i < offset && i < source.length(); i++)
|
||||
{
|
||||
if (source.charAt(i) == '\n')
|
||||
{
|
||||
line++;
|
||||
column = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
return line + ":" + column + ": " + diag.getMessage(Locale.getDefault());
|
||||
}
|
||||
|
||||
protected void run()
|
||||
{
|
||||
String text = textArea.getText();
|
||||
executor.submit(() ->
|
||||
{
|
||||
shell.snippets()
|
||||
.filter(v -> !prelude.contains(v))
|
||||
.forEach(shell::drop);
|
||||
|
||||
cleanup();
|
||||
|
||||
eval(text, true);
|
||||
});
|
||||
}
|
||||
|
||||
public void freeContext()
|
||||
{
|
||||
cleanup();
|
||||
|
||||
exec = null;
|
||||
shell = null;
|
||||
prelude = null;
|
||||
injector = null;
|
||||
|
||||
if (autoCompletion != null)
|
||||
{
|
||||
autoCompletion.uninstall();
|
||||
}
|
||||
autoCompletion = null;
|
||||
|
||||
console.setText("");
|
||||
}
|
||||
|
||||
private void cleanup()
|
||||
{
|
||||
for (var c : cleanup)
|
||||
{
|
||||
try
|
||||
{
|
||||
c.run();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
shellLogger.error("Cleanup threw:", e);
|
||||
}
|
||||
}
|
||||
cleanup.clear();
|
||||
}
|
||||
|
||||
protected abstract void invokeOnClientThread(Runnable r);
|
||||
|
||||
public <T> T inject(Class<T> clazz)
|
||||
{
|
||||
return injector.getInstance(clazz);
|
||||
}
|
||||
|
||||
public void cleanup(Runnable r)
|
||||
{
|
||||
cleanup.add(r);
|
||||
}
|
||||
}
|
||||
483
runelite-jshell/src/main/java/net/runelite/jshell/TeeLogger.java
Normal file
483
runelite-jshell/src/main/java/net/runelite/jshell/TeeLogger.java
Normal file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.jshell;
|
||||
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.Consumer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.helpers.FormattingTuple;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
||||
@SuppressWarnings("PlaceholderCountMatchesArgumentCount")
|
||||
@RequiredArgsConstructor
|
||||
public class TeeLogger implements Logger
|
||||
{
|
||||
private static final String TRACE = "[TRACE] ";
|
||||
private static final String DEBUG = "[DEBUG] ";
|
||||
private static final String INFO = "[INFO] ";
|
||||
private static final String WARN = "[WARN] ";
|
||||
private static final String ERROR = "[ERROR] ";
|
||||
|
||||
private final Logger delegate;
|
||||
private final Consumer<String> messageConsumer;
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "OPRSShell";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private void log(String level, String message, Object... format)
|
||||
{
|
||||
FormattingTuple fmt = MessageFormatter.arrayFormat(message, format);
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(level).append(fmt.getMessage());
|
||||
Throwable throwable = fmt.getThrowable();
|
||||
if (throwable != null)
|
||||
{
|
||||
msg.append("\n");
|
||||
var caw = new CharArrayWriter();
|
||||
try (PrintWriter pw = new PrintWriter(caw))
|
||||
{
|
||||
throwable.printStackTrace(pw);
|
||||
}
|
||||
msg.append(caw.toString());
|
||||
}
|
||||
messageConsumer.accept(msg.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(String msg)
|
||||
{
|
||||
delegate.trace(msg);
|
||||
log(TRACE, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(String format, Object arg)
|
||||
{
|
||||
delegate.trace(format, arg);
|
||||
log(TRACE, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.trace(format, arg1, arg2);
|
||||
log(TRACE, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(String format, Object... arguments)
|
||||
{
|
||||
delegate.trace(format, arguments);
|
||||
log(TRACE, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(String msg, Throwable t)
|
||||
{
|
||||
delegate.trace(msg, t);
|
||||
log(TRACE, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled(Marker marker)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String msg)
|
||||
{
|
||||
delegate.trace(marker, msg);
|
||||
log(TRACE, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String format, Object arg)
|
||||
{
|
||||
delegate.trace(marker, format, arg);
|
||||
log(TRACE, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.trace(marker, format, arg1, arg2);
|
||||
log(TRACE, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String format, Object... argArray)
|
||||
{
|
||||
delegate.trace(marker, format, argArray);
|
||||
log(TRACE, format, argArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String msg, Throwable t)
|
||||
{
|
||||
delegate.trace(marker, msg, t);
|
||||
log(TRACE, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String msg)
|
||||
{
|
||||
delegate.debug(msg);
|
||||
log(DEBUG, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String format, Object arg)
|
||||
{
|
||||
delegate.debug(format, arg);
|
||||
log(DEBUG, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.debug(format, arg1, arg2);
|
||||
log(DEBUG, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String format, Object... arguments)
|
||||
{
|
||||
delegate.debug(format, arguments);
|
||||
log(DEBUG, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String msg, Throwable t)
|
||||
{
|
||||
delegate.debug(msg, t);
|
||||
log(DEBUG, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled(Marker marker)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String msg)
|
||||
{
|
||||
delegate.debug(marker, msg);
|
||||
log(DEBUG, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String format, Object arg)
|
||||
{
|
||||
delegate.debug(marker, format, arg);
|
||||
log(DEBUG, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.debug(marker, format, arg1, arg2);
|
||||
log(DEBUG, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String format, Object... arguments)
|
||||
{
|
||||
delegate.debug(marker, format, arguments);
|
||||
log(DEBUG, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String msg, Throwable t)
|
||||
{
|
||||
delegate.debug(marker, msg, t);
|
||||
log(DEBUG, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String msg)
|
||||
{
|
||||
delegate.info(msg);
|
||||
log(INFO, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String format, Object arg)
|
||||
{
|
||||
delegate.info(format, arg);
|
||||
log(INFO, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.info(format, arg1, arg2);
|
||||
log(INFO, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String format, Object... arguments)
|
||||
{
|
||||
delegate.info(format, arguments);
|
||||
log(INFO, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String msg, Throwable t)
|
||||
{
|
||||
delegate.info(msg, t);
|
||||
log(INFO, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled(Marker marker)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String msg)
|
||||
{
|
||||
delegate.info(marker, msg);
|
||||
log(INFO, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String format, Object arg)
|
||||
{
|
||||
delegate.info(marker, format, arg);
|
||||
log(INFO, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.info(marker, format, arg1, arg2);
|
||||
log(INFO, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String format, Object... arguments)
|
||||
{
|
||||
delegate.info(marker, format, arguments);
|
||||
log(INFO, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String msg, Throwable t)
|
||||
{
|
||||
delegate.info(marker, msg, t);
|
||||
log(INFO, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String msg)
|
||||
{
|
||||
delegate.warn(msg);
|
||||
log(WARN, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String format, Object arg)
|
||||
{
|
||||
delegate.warn(format, arg);
|
||||
log(WARN, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String format, Object... arguments)
|
||||
{
|
||||
delegate.warn(format, arguments);
|
||||
log(WARN, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.warn(format, arg1, arg2);
|
||||
log(WARN, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String msg, Throwable t)
|
||||
{
|
||||
delegate.warn(msg, t);
|
||||
log(WARN, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled(Marker marker)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String msg)
|
||||
{
|
||||
delegate.warn(marker, msg);
|
||||
log(WARN, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String format, Object arg)
|
||||
{
|
||||
delegate.warn(marker, format, arg);
|
||||
log(WARN, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.warn(marker, format, arg1, arg2);
|
||||
log(WARN, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String format, Object... arguments)
|
||||
{
|
||||
delegate.warn(marker, format, arguments);
|
||||
log(WARN, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String msg, Throwable t)
|
||||
{
|
||||
delegate.warn(marker, msg, t);
|
||||
log(WARN, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String msg)
|
||||
{
|
||||
delegate.error(msg);
|
||||
log(ERROR, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String format, Object arg)
|
||||
{
|
||||
delegate.error(format, arg);
|
||||
log(ERROR, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.error(format, arg1, arg2);
|
||||
log(ERROR, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String format, Object... arguments)
|
||||
{
|
||||
delegate.error(format, arguments);
|
||||
log(ERROR, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String msg, Throwable t)
|
||||
{
|
||||
delegate.error(msg, t);
|
||||
log(ERROR, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled(Marker marker)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String msg)
|
||||
{
|
||||
delegate.error(marker, msg);
|
||||
log(ERROR, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String format, Object arg)
|
||||
{
|
||||
delegate.error(marker, format, arg);
|
||||
log(ERROR, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String format, Object arg1, Object arg2)
|
||||
{
|
||||
delegate.error(marker, format, arg1, arg2);
|
||||
log(ERROR, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String format, Object... arguments)
|
||||
{
|
||||
delegate.error(marker, format, arguments);
|
||||
log(ERROR, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String msg, Throwable t)
|
||||
{
|
||||
delegate.error(marker, msg, t);
|
||||
log(ERROR, msg, t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE RSyntaxTheme SYSTEM "theme.dtd">
|
||||
|
||||
<RSyntaxTheme version="1.0">
|
||||
<!-- General editor colors. -->
|
||||
<background color="2B2B2B"/>
|
||||
<caret color="BBBBBB"/>
|
||||
<selection useFG="false" bg="214283" roundedEdges="false"/>
|
||||
<currentLineHighlight color="323232" fade="false"/>
|
||||
<marginLine fg="394448"/>
|
||||
<markAllHighlight color="155221"/>
|
||||
<markOccurrencesHighlight color="32593D" border="true"/>
|
||||
<matchedBracket fg="A9B7C6" bg="2E2E2E" highlightBoth="true" animate="true"/><!--ij draws a border-->
|
||||
<hyperlinks fg="287BDE"/>
|
||||
<secondaryLanguages>
|
||||
<language index="1" bg="333344"/>
|
||||
<language index="2" bg="223322"/>
|
||||
<language index="3" bg="332222"/>
|
||||
</secondaryLanguages>
|
||||
|
||||
<!-- Gutter styling. -->
|
||||
<gutterBorder color="606366"/>
|
||||
<lineNumbers fg="606366"/>
|
||||
<foldIndicator fg="6A8088" iconBg="2f383c" iconArmedBg="3f484c"/>
|
||||
<iconRowHeader activeLineRange="878787"/>
|
||||
|
||||
<!-- Syntax tokens. -->
|
||||
<tokenStyles>
|
||||
<style token="IDENTIFIER" fg="A9B7C6"/>
|
||||
<style token="RESERVED_WORD" fg="CC7832" bold="false"/>
|
||||
<style token="RESERVED_WORD_2" fg="CC7832" bold="false"/>
|
||||
<style token="ANNOTATION" fg="BBB529"/>
|
||||
<style token="COMMENT_DOCUMENTATION" fg="629755"/>
|
||||
<style token="COMMENT_EOL" fg="808080"/>
|
||||
<style token="COMMENT_MULTILINE" fg="808080"/>
|
||||
<style token="COMMENT_KEYWORD" fg="629755"/>
|
||||
<style token="COMMENT_MARKUP" fg="77B767"/>
|
||||
<style token="FUNCTION" fg="A9B7C6"/><!-- any identifier magically known -->
|
||||
<style token="DATA_TYPE" fg="CC7832" bold="false"/>
|
||||
<style token="LITERAL_BOOLEAN" fg="CC7832" bold="false"/>
|
||||
<style token="LITERAL_NUMBER_DECIMAL_INT" fg="6897BB"/>
|
||||
<style token="LITERAL_NUMBER_FLOAT" fg="6897BB"/>
|
||||
<style token="LITERAL_NUMBER_HEXADECIMAL" fg="6897BB"/>
|
||||
<style token="LITERAL_STRING_DOUBLE_QUOTE" fg="6A8759"/>
|
||||
<style token="LITERAL_CHAR" fg="6A8759"/>
|
||||
<style token="LITERAL_BACKQUOTE" fg="6A8759"/>
|
||||
|
||||
<!-- all wrong but nobody will write xml in this -->
|
||||
<style token="MARKUP_TAG_DELIMITER" fg="F92672"/>
|
||||
<style token="MARKUP_TAG_NAME" fg="ABBFD3" bold="true"/>
|
||||
<style token="MARKUP_TAG_ATTRIBUTE" fg="B3B689"/>
|
||||
<style token="MARKUP_TAG_ATTRIBUTE_VALUE" fg="e1e2cf"/>
|
||||
<style token="MARKUP_COMMENT" fg="878787"/>
|
||||
<style token="MARKUP_DTD" fg="A082BD"/>
|
||||
<style token="MARKUP_PROCESSING_INSTRUCTION" fg="A082BD"/>
|
||||
<style token="MARKUP_CDATA" fg="d5e6f0"/>
|
||||
<style token="MARKUP_CDATA_DELIMITER" fg="FD971F"/>
|
||||
<style token="MARKUP_ENTITY_REFERENCE" fg="F92672"/>
|
||||
|
||||
<style token="OPERATOR" fg="A9B7C6"/>
|
||||
<style token="PREPROCESSOR" fg="A082BD"/>
|
||||
<style token="REGEX" fg="6A8759"/>
|
||||
<style token="SEPARATOR" fg="A9B7C6"/>
|
||||
<style token="VARIABLE" fg="A9B7C6" bold="false"/>
|
||||
<style token="WHITESPACE" fg="606060"/>
|
||||
|
||||
<style token="ERROR_IDENTIFIER" fg="F9F9F9" bg="d82323"/>
|
||||
<style token="ERROR_NUMBER_FORMAT" fg="F9F9F9" bg="d82323"/>
|
||||
<style token="ERROR_STRING_DOUBLE" fg="F9F9F9" bg="d82323"/>
|
||||
<style token="ERROR_CHAR" fg="F9F9F9" bg="d82323"/>
|
||||
</tokenStyles>
|
||||
|
||||
</RSyntaxTheme>
|
||||
@@ -0,0 +1,8 @@
|
||||
// Welcome to the OpenOSRS Development Shell
|
||||
// Everything executed here runs on the client thread by default.
|
||||
// By default client, clientThread, configManager and log are in scope
|
||||
// You can subscribe to the Event Bus by using subscribe(Event.class, ev -> handler);
|
||||
// and you can access things in the global injector module with var thing = inject(Thing.class);
|
||||
// Press Ctrl+R or F10 to execute the contents of this editor
|
||||
|
||||
log.info("Hello {}", client.getGameState());
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.*;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.coords.*;
|
||||
import net.runelite.api.events.*;
|
||||
import net.runelite.api.widgets.*;
|
||||
import net.runelite.client.events.*;
|
||||
import net.runelite.client.game.*;
|
||||
|
||||
var $PANEL = net.runelite.jshell.ShellPanel.INSTANCE;
|
||||
Logger log = $PANEL.getShellLogger();
|
||||
|
||||
static <T> T inject(Class<T> clazz)
|
||||
{
|
||||
return $PANEL.inject(clazz);
|
||||
}
|
||||
|
||||
static void cleanup(Runnable r)
|
||||
{
|
||||
$PANEL.cleanup(r);
|
||||
}
|
||||
|
||||
var $EVENT_BUS = inject(net.runelite.client.eventbus.EventBus.class);
|
||||
static <T> void subscribe(Class<T> eventType, Consumer<T> subscriber, float priority)
|
||||
{
|
||||
var sub = $EVENT_BUS.register(eventType, subscriber, priority);
|
||||
cleanup(() -> $EVENT_BUS.unregister(sub));
|
||||
}
|
||||
static <T> void subscribe(Class<T> eventType, Consumer<T> subscriber)
|
||||
{
|
||||
var sub = $EVENT_BUS.register(eventType, subscriber, 0.f);
|
||||
cleanup(() -> $EVENT_BUS.unregister(sub));
|
||||
}
|
||||
|
||||
var client = inject(Client.class);
|
||||
var clientThread = inject(ClientThread.class);
|
||||
var configManager = inject(ConfigManager.class);
|
||||
|
||||
@@ -167,18 +167,36 @@ public interface RSActor extends RSRenderable, Actor
|
||||
@Override
|
||||
int getWalkAnimation();
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
@Import("walkBackSequence")
|
||||
@Override
|
||||
int getWalkBackAnimation();
|
||||
|
||||
@Import("walkBackSequence")
|
||||
@Override
|
||||
int getWalkRotate180();
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
@Import("walkLeftSequence")
|
||||
@Override
|
||||
int getWalkLeftAnimation();
|
||||
|
||||
@Import("walkLeftSequence")
|
||||
@Override
|
||||
int getWalkRotateLeft();
|
||||
|
||||
// TODO: Remove next major
|
||||
@Deprecated
|
||||
@Import("walkRightSequence")
|
||||
@Override
|
||||
int getWalkRightAnimation();
|
||||
|
||||
@Import("walkRightSequence")
|
||||
@Override
|
||||
int getWalkRotateRight();
|
||||
|
||||
@Import("runSequence")
|
||||
@Override
|
||||
int getRunAnimation();
|
||||
|
||||
@@ -42,6 +42,7 @@ include(":injection-annotations")
|
||||
include(":injector")
|
||||
include(":runelite-api")
|
||||
include(":runelite-client")
|
||||
include(":runelite-jshell")
|
||||
include(":runelite-mixins")
|
||||
include(":runelite-script-assembler-plugin")
|
||||
include(":runescape-api")
|
||||
|
||||
Reference in New Issue
Block a user