Merge pull request #13277 from abextm/jshell
devtools: add shell window
This commit is contained in:
34
pom.xml
34
pom.xml
@@ -119,6 +119,7 @@
|
|||||||
<module>cache-updater</module>
|
<module>cache-updater</module>
|
||||||
<module>runelite-api</module>
|
<module>runelite-api</module>
|
||||||
<module>runelite-client</module>
|
<module>runelite-client</module>
|
||||||
|
<module>runelite-jshell</module>
|
||||||
<module>runelite-script-assembler-plugin</module>
|
<module>runelite-script-assembler-plugin</module>
|
||||||
<module>http-api</module>
|
<module>http-api</module>
|
||||||
<module>http-service</module>
|
<module>http-service</module>
|
||||||
@@ -142,6 +143,11 @@
|
|||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.8.5</version>
|
<version>2.8.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
|
<artifactId>jsr305</artifactId>
|
||||||
|
<version>3.0.2</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-parent</artifactId>
|
<artifactId>logback-parent</artifactId>
|
||||||
@@ -149,37 +155,25 @@
|
|||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject</groupId>
|
||||||
|
<artifactId>guice-bom</artifactId>
|
||||||
|
<version>4.1.0</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>java9</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[1.9,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<release>${java.release}</release>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.6.1</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${java.version}</source>
|
<source>${java.version}</source>
|
||||||
<target>${java.version}</target>
|
<target>${java.version}</target>
|
||||||
|
<release>${java.release}</release>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
<artifactId>jsr305</artifactId>
|
<artifactId>jsr305</artifactId>
|
||||||
<version>3.0.2</version>
|
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,6 @@
|
|||||||
<name>RuneLite Client</name>
|
<name>RuneLite Client</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<guice.version>4.1.0</guice.version>
|
|
||||||
|
|
||||||
<jarsigner.skip>true</jarsigner.skip>
|
<jarsigner.skip>true</jarsigner.skip>
|
||||||
<pmd.skip>true</pmd.skip>
|
<pmd.skip>true</pmd.skip>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -85,7 +83,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.inject</groupId>
|
<groupId>com.google.inject</groupId>
|
||||||
<artifactId>guice</artifactId>
|
<artifactId>guice</artifactId>
|
||||||
<version>${guice.version}</version>
|
|
||||||
<classifier>no_aop</classifier>
|
<classifier>no_aop</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -215,7 +212,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
<artifactId>jsr305</artifactId>
|
<artifactId>jsr305</artifactId>
|
||||||
<version>3.0.2</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -223,6 +219,12 @@
|
|||||||
<artifactId>runelite-api</artifactId>
|
<artifactId>runelite-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.runelite</groupId>
|
||||||
|
<artifactId>jshell</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.runelite</groupId>
|
<groupId>net.runelite</groupId>
|
||||||
<artifactId>client-patch</artifactId>
|
<artifactId>client-patch</artifactId>
|
||||||
@@ -267,13 +269,11 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.inject.extensions</groupId>
|
<groupId>com.google.inject.extensions</groupId>
|
||||||
<artifactId>guice-testlib</artifactId>
|
<artifactId>guice-testlib</artifactId>
|
||||||
<version>${guice.version}</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.inject.extensions</groupId>
|
<groupId>com.google.inject.extensions</groupId>
|
||||||
<artifactId>guice-grapher</artifactId>
|
<artifactId>guice-grapher</artifactId>
|
||||||
<version>${guice.version}</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -318,7 +318,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.2.1</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
|
|||||||
@@ -51,26 +51,20 @@ import net.runelite.client.util.ReflectUtil;
|
|||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class EventBus
|
public class EventBus
|
||||||
{
|
{
|
||||||
@FunctionalInterface
|
|
||||||
public interface SubscriberMethod
|
|
||||||
{
|
|
||||||
void invoke(Object event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
private static class Subscriber
|
public static class Subscriber
|
||||||
{
|
{
|
||||||
private final Object object;
|
private final Object object;
|
||||||
private final Method method;
|
private final Method method;
|
||||||
private final float priority;
|
private final float priority;
|
||||||
@EqualsAndHashCode.Exclude
|
@EqualsAndHashCode.Exclude
|
||||||
private final SubscriberMethod lamda;
|
private final Consumer<Object> lambda;
|
||||||
|
|
||||||
void invoke(final Object arg) throws Exception
|
void invoke(final Object arg) throws Exception
|
||||||
{
|
{
|
||||||
if (lamda != null)
|
if (lambda != null)
|
||||||
{
|
{
|
||||||
lamda.invoke(arg);
|
lambda.accept(arg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -80,7 +74,9 @@ public class EventBus
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Consumer<Throwable> exceptionHandler;
|
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
|
* Instantiates EventBus with default exception handler
|
||||||
@@ -99,13 +95,8 @@ public class EventBus
|
|||||||
*/
|
*/
|
||||||
public synchronized void register(@Nonnull final Object object)
|
public synchronized void register(@Nonnull final Object object)
|
||||||
{
|
{
|
||||||
final ImmutableMultimap.Builder<Class, Subscriber> builder = ImmutableMultimap.builder();
|
final ImmutableMultimap.Builder<Class<?>, Subscriber> builder = ImmutableMultimap.builder();
|
||||||
|
builder.putAll(subscribers);
|
||||||
if (subscribers != null)
|
|
||||||
{
|
|
||||||
builder.putAll(subscribers);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.orderValuesBy(Comparator.comparing(Subscriber::getPriority).reversed()
|
builder.orderValuesBy(Comparator.comparing(Subscriber::getPriority).reversed()
|
||||||
.thenComparing(s -> s.object.getClass().getName()));
|
.thenComparing(s -> s.object.getClass().getName()));
|
||||||
|
|
||||||
@@ -141,7 +132,7 @@ public class EventBus
|
|||||||
Preconditions.checkArgument(method.getName().equals(preferredName), "Subscribed method " + method + " should be named " + preferredName);
|
Preconditions.checkArgument(method.getName().equals(preferredName), "Subscribed method " + method + " should be named " + preferredName);
|
||||||
|
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
SubscriberMethod lambda = null;
|
Consumer<Object> lambda = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -150,14 +141,14 @@ public class EventBus
|
|||||||
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
|
final MethodHandle target = caller.findVirtual(clazz, method.getName(), subscription);
|
||||||
final CallSite site = LambdaMetafactory.metafactory(
|
final CallSite site = LambdaMetafactory.metafactory(
|
||||||
caller,
|
caller,
|
||||||
"invoke",
|
"accept",
|
||||||
MethodType.methodType(SubscriberMethod.class, clazz),
|
MethodType.methodType(Consumer.class, clazz),
|
||||||
subscription.changeParameterType(0, Object.class),
|
subscription.changeParameterType(0, Object.class),
|
||||||
target,
|
target,
|
||||||
subscription);
|
subscription);
|
||||||
|
|
||||||
final MethodHandle factory = site.getTarget();
|
final MethodHandle factory = site.getTarget();
|
||||||
lambda = (SubscriberMethod) factory.bindTo(object).invokeExact();
|
lambda = (Consumer<Object>) factory.bindTo(object).invokeExact();
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
@@ -173,6 +164,21 @@ public class EventBus
|
|||||||
subscribers = builder.build();
|
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.
|
* Unregisters all subscribed methods from provided subscriber object.
|
||||||
*
|
*
|
||||||
@@ -180,12 +186,7 @@ public class EventBus
|
|||||||
*/
|
*/
|
||||||
public synchronized void unregister(@Nonnull final Object object)
|
public synchronized void unregister(@Nonnull final Object object)
|
||||||
{
|
{
|
||||||
if (subscribers == null)
|
final Multimap<Class<?>, Subscriber> map = HashMultimap.create();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Multimap<Class, Subscriber> map = HashMultimap.create();
|
|
||||||
map.putAll(subscribers);
|
map.putAll(subscribers);
|
||||||
|
|
||||||
for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
|
for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass())
|
||||||
@@ -207,6 +208,21 @@ public class EventBus
|
|||||||
subscribers = ImmutableMultimap.copyOf(map);
|
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,
|
* Posts provided event to all registered subscribers. Subscriber calls are invoked immediately,
|
||||||
* ordered by priority then their declaring class' name.
|
* ordered by priority then their declaring class' name.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import java.awt.Color;
|
|||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
class DevToolsButton extends JButton
|
public class DevToolsButton extends JButton
|
||||||
{
|
{
|
||||||
@Getter
|
@Getter
|
||||||
private boolean active;
|
private boolean active;
|
||||||
@@ -53,4 +53,20 @@ class DevToolsButton extends JButton
|
|||||||
setBackground(null);
|
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;
|
package net.runelite.client.plugins.devtools;
|
||||||
|
|
||||||
|
import com.google.inject.ProvisionException;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.awt.TrayIcon;
|
import java.awt.TrayIcon;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
@@ -32,6 +33,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.MenuAction;
|
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.ui.overlay.infobox.InfoBoxManager;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
class DevToolsPanel extends PluginPanel
|
class DevToolsPanel extends PluginPanel
|
||||||
{
|
{
|
||||||
private final Client client;
|
private final Client client;
|
||||||
@@ -129,30 +132,10 @@ class DevToolsPanel extends PluginPanel
|
|||||||
});
|
});
|
||||||
|
|
||||||
container.add(plugin.getWidgetInspector());
|
container.add(plugin.getWidgetInspector());
|
||||||
plugin.getWidgetInspector().addActionListener((ev) ->
|
plugin.getWidgetInspector().addFrame(widgetInspector);
|
||||||
{
|
|
||||||
if (plugin.getWidgetInspector().isActive())
|
|
||||||
{
|
|
||||||
widgetInspector.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
widgetInspector.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
container.add(plugin.getVarInspector());
|
container.add(plugin.getVarInspector());
|
||||||
plugin.getVarInspector().addActionListener((ev) ->
|
plugin.getVarInspector().addFrame(varInspector);
|
||||||
{
|
|
||||||
if (plugin.getVarInspector().isActive())
|
|
||||||
{
|
|
||||||
varInspector.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
varInspector.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
container.add(plugin.getSoundEffects());
|
container.add(plugin.getSoundEffects());
|
||||||
|
|
||||||
@@ -164,17 +147,7 @@ class DevToolsPanel extends PluginPanel
|
|||||||
container.add(notificationBtn);
|
container.add(notificationBtn);
|
||||||
|
|
||||||
container.add(plugin.getScriptInspector());
|
container.add(plugin.getScriptInspector());
|
||||||
plugin.getScriptInspector().addActionListener((ev) ->
|
plugin.getScriptInspector().addFrame(scriptInspector);
|
||||||
{
|
|
||||||
if (plugin.getScriptInspector().isActive())
|
|
||||||
{
|
|
||||||
scriptInspector.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scriptInspector.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final JButton newInfoboxBtn = new JButton("Infobox");
|
final JButton newInfoboxBtn = new JButton("Infobox");
|
||||||
newInfoboxBtn.addActionListener(e ->
|
newInfoboxBtn.addActionListener(e ->
|
||||||
@@ -198,22 +171,27 @@ class DevToolsPanel extends PluginPanel
|
|||||||
container.add(clearInfoboxBtn);
|
container.add(clearInfoboxBtn);
|
||||||
|
|
||||||
container.add(plugin.getInventoryInspector());
|
container.add(plugin.getInventoryInspector());
|
||||||
plugin.getInventoryInspector().addActionListener((ev) ->
|
plugin.getInventoryInspector().addFrame(inventoryInspector);
|
||||||
{
|
|
||||||
if (plugin.getInventoryInspector().isActive())
|
|
||||||
{
|
|
||||||
inventoryInspector.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inventoryInspector.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final JButton disconnectBtn = new JButton("Disconnect");
|
final JButton disconnectBtn = new JButton("Disconnect");
|
||||||
disconnectBtn.addActionListener(e -> clientThread.invoke(() -> client.setGameState(GameState.CONNECTION_LOST)));
|
disconnectBtn.addActionListener(e -> clientThread.invoke(() -> client.setGameState(GameState.CONNECTION_LOST)));
|
||||||
container.add(disconnectBtn);
|
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;
|
return container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ public class DevToolsPlugin extends Plugin
|
|||||||
private DevToolsButton soundEffects;
|
private DevToolsButton soundEffects;
|
||||||
private DevToolsButton scriptInspector;
|
private DevToolsButton scriptInspector;
|
||||||
private DevToolsButton inventoryInspector;
|
private DevToolsButton inventoryInspector;
|
||||||
|
private DevToolsButton shell;
|
||||||
private NavigationButton navButton;
|
private NavigationButton navButton;
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@@ -187,6 +188,7 @@ public class DevToolsPlugin extends Plugin
|
|||||||
soundEffects = new DevToolsButton("Sound Effects");
|
soundEffects = new DevToolsButton("Sound Effects");
|
||||||
scriptInspector = new DevToolsButton("Script Inspector");
|
scriptInspector = new DevToolsButton("Script Inspector");
|
||||||
inventoryInspector = new DevToolsButton("Inventory Inspector");
|
inventoryInspector = new DevToolsButton("Inventory Inspector");
|
||||||
|
shell = new DevToolsButton("Shell");
|
||||||
|
|
||||||
overlayManager.add(overlay);
|
overlayManager.add(overlay);
|
||||||
overlayManager.add(locationOverlay);
|
overlayManager.add(locationOverlay);
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.AdjustmentEvent;
|
import java.awt.event.AdjustmentEvent;
|
||||||
import java.awt.event.AdjustmentListener;
|
import java.awt.event.AdjustmentListener;
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -39,7 +37,6 @@ import javax.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollBar;
|
import javax.swing.JScrollBar;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
@@ -65,7 +62,7 @@ import net.runelite.client.ui.ColorScheme;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Singleton
|
@Singleton
|
||||||
class InventoryInspector extends JFrame
|
class InventoryInspector extends DevToolsFrame
|
||||||
{
|
{
|
||||||
private static final int MAX_LOG_ENTRIES = 25;
|
private static final int MAX_LOG_ENTRIES = 25;
|
||||||
|
|
||||||
@@ -80,7 +77,7 @@ class InventoryInspector extends JFrame
|
|||||||
private final InventoryDeltaPanel deltaPanel;
|
private final InventoryDeltaPanel deltaPanel;
|
||||||
|
|
||||||
@Inject
|
@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.client = client;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
@@ -92,18 +89,6 @@ class InventoryInspector extends JFrame
|
|||||||
setTitle("RuneLite Inventory Inspector");
|
setTitle("RuneLite Inventory Inspector");
|
||||||
setIconImage(ClientUI.ICON);
|
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.setBorder(new EmptyBorder(2, 2, 2, 2));
|
||||||
tree.setRootVisible(false);
|
tree.setRootVisible(false);
|
||||||
tree.setShowsRootHandles(true);
|
tree.setShowsRootHandles(true);
|
||||||
@@ -175,19 +160,19 @@ class InventoryInspector extends JFrame
|
|||||||
pack();
|
pack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void open()
|
public void open()
|
||||||
{
|
{
|
||||||
eventBus.register(this);
|
eventBus.register(this);
|
||||||
setVisible(true);
|
super.open();
|
||||||
toFront();
|
|
||||||
repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
eventBus.unregister(this);
|
eventBus.unregister(this);
|
||||||
clearTracker();
|
clearTracker();
|
||||||
setVisible(false);
|
super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import java.awt.Dimension;
|
|||||||
import java.awt.FlowLayout;
|
import java.awt.FlowLayout;
|
||||||
import java.awt.event.AdjustmentEvent;
|
import java.awt.event.AdjustmentEvent;
|
||||||
import java.awt.event.AdjustmentListener;
|
import java.awt.event.AdjustmentListener;
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -42,7 +40,6 @@ import javax.swing.BorderFactory;
|
|||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JFormattedTextField;
|
import javax.swing.JFormattedTextField;
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JPanel;
|
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.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.EventBus;
|
import net.runelite.client.eventbus.EventBus;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
import net.runelite.client.ui.ClientUI;
|
|
||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.DynamicGridLayout;
|
import net.runelite.client.ui.DynamicGridLayout;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.util.Text;
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
@Slf4j
|
@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.
|
// These scripts are the only ones that fire every client tick regardless of location.
|
||||||
private final static String DEFAULT_BLACKLIST = "3174,1004";
|
private final static String DEFAULT_BLACKLIST = "3174,1004";
|
||||||
@@ -139,28 +135,16 @@ public class ScriptInspector extends JFrame
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ScriptInspector(Client client, EventBus eventBus, DevToolsPlugin plugin, ConfigManager configManager)
|
ScriptInspector(Client client, EventBus eventBus, ConfigManager configManager)
|
||||||
{
|
{
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.configManager = configManager;
|
this.configManager = configManager;
|
||||||
|
|
||||||
setTitle("RuneLite Script Inspector");
|
setTitle("RuneLite Script Inspector");
|
||||||
setIconImage(ClientUI.ICON);
|
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
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));
|
tracker.setLayout(new DynamicGridLayout(0, 1, 0, 3));
|
||||||
|
|
||||||
final JPanel leftSide = new JPanel();
|
final JPanel leftSide = new JPanel();
|
||||||
@@ -344,14 +328,14 @@ public class ScriptInspector extends JFrame
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void open()
|
public void open()
|
||||||
{
|
{
|
||||||
eventBus.register(this);
|
eventBus.register(this);
|
||||||
setVisible(true);
|
super.open();
|
||||||
toFront();
|
|
||||||
repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
configManager.setConfiguration("devtools", "highlights",
|
configManager.setConfiguration("devtools", "highlights",
|
||||||
@@ -360,7 +344,7 @@ public class ScriptInspector extends JFrame
|
|||||||
Text.toCSV(Lists.transform(new ArrayList<>(blacklist), String::valueOf)));
|
Text.toCSV(Lists.transform(new ArrayList<>(blacklist), String::valueOf)));
|
||||||
currentNode = null;
|
currentNode = null;
|
||||||
eventBus.unregister(this);
|
eventBus.unregister(this);
|
||||||
setVisible(false);
|
super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addScriptLog(ScriptTreeNode treeNode)
|
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("RuneLite 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.FlowLayout;
|
||||||
import java.awt.event.AdjustmentEvent;
|
import java.awt.event.AdjustmentEvent;
|
||||||
import java.awt.event.AdjustmentListener;
|
import java.awt.event.AdjustmentListener;
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollBar;
|
import javax.swing.JScrollBar;
|
||||||
@@ -62,13 +59,12 @@ import net.runelite.api.events.VarbitChanged;
|
|||||||
import net.runelite.client.callback.ClientThread;
|
import net.runelite.client.callback.ClientThread;
|
||||||
import net.runelite.client.eventbus.EventBus;
|
import net.runelite.client.eventbus.EventBus;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
import net.runelite.client.ui.ClientUI;
|
|
||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.DynamicGridLayout;
|
import net.runelite.client.ui.DynamicGridLayout;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class VarInspector extends JFrame
|
class VarInspector extends DevToolsFrame
|
||||||
{
|
{
|
||||||
@Getter
|
@Getter
|
||||||
private enum VarType
|
private enum VarType
|
||||||
@@ -106,28 +102,16 @@ class VarInspector extends JFrame
|
|||||||
private Map<Integer, Object> varcs = null;
|
private Map<Integer, Object> varcs = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VarInspector(Client client, ClientThread clientThread, EventBus eventBus, DevToolsPlugin plugin)
|
VarInspector(Client client, ClientThread clientThread, EventBus eventBus)
|
||||||
{
|
{
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.clientThread = clientThread;
|
this.clientThread = clientThread;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
|
|
||||||
setTitle("RuneLite Var Inspector");
|
setTitle("RuneLite Var Inspector");
|
||||||
setIconImage(ClientUI.ICON);
|
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
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));
|
tracker.setLayout(new DynamicGridLayout(0, 1, 0, 3));
|
||||||
|
|
||||||
final JPanel trackerWrapper = new JPanel();
|
final JPanel trackerWrapper = new JPanel();
|
||||||
@@ -332,6 +316,7 @@ class VarInspector extends JFrame
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void open()
|
public void open()
|
||||||
{
|
{
|
||||||
if (oldVarps == null)
|
if (oldVarps == null)
|
||||||
@@ -361,16 +346,15 @@ class VarInspector extends JFrame
|
|||||||
});
|
});
|
||||||
|
|
||||||
eventBus.register(this);
|
eventBus.register(this);
|
||||||
setVisible(true);
|
super.open();
|
||||||
toFront();
|
|
||||||
repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
|
super.close();
|
||||||
tracker.removeAll();
|
tracker.removeAll();
|
||||||
eventBus.unregister(this);
|
eventBus.unregister(this);
|
||||||
setVisible(false);
|
|
||||||
varcs = null;
|
varcs = null;
|
||||||
varbits = null;
|
varbits = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ import com.google.inject.Singleton;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
@@ -43,7 +41,6 @@ import java.util.Stack;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
@@ -73,13 +70,12 @@ import net.runelite.api.widgets.WidgetType;
|
|||||||
import net.runelite.client.callback.ClientThread;
|
import net.runelite.client.callback.ClientThread;
|
||||||
import net.runelite.client.eventbus.EventBus;
|
import net.runelite.client.eventbus.EventBus;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
import net.runelite.client.ui.ClientUI;
|
|
||||||
import net.runelite.client.ui.overlay.OverlayManager;
|
import net.runelite.client.ui.overlay.OverlayManager;
|
||||||
import net.runelite.client.util.ColorUtil;
|
import net.runelite.client.util.ColorUtil;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Singleton
|
@Singleton
|
||||||
class WidgetInspector extends JFrame
|
class WidgetInspector extends DevToolsFrame
|
||||||
{
|
{
|
||||||
private static final Map<Integer, WidgetInfo> widgetIdMap = new HashMap<>();
|
private static final Map<Integer, WidgetInfo> widgetIdMap = new HashMap<>();
|
||||||
|
|
||||||
@@ -123,7 +119,6 @@ class WidgetInspector extends JFrame
|
|||||||
ClientThread clientThread,
|
ClientThread clientThread,
|
||||||
WidgetInfoTableModel infoTableModel,
|
WidgetInfoTableModel infoTableModel,
|
||||||
DevToolsConfig config,
|
DevToolsConfig config,
|
||||||
DevToolsPlugin plugin,
|
|
||||||
EventBus eventBus,
|
EventBus eventBus,
|
||||||
Provider<WidgetInspectorOverlay> overlay,
|
Provider<WidgetInspectorOverlay> overlay,
|
||||||
OverlayManager overlayManager)
|
OverlayManager overlayManager)
|
||||||
@@ -138,18 +133,6 @@ class WidgetInspector extends JFrame
|
|||||||
eventBus.register(this);
|
eventBus.register(this);
|
||||||
|
|
||||||
setTitle("RuneLite Widget Inspector");
|
setTitle("RuneLite 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());
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
@@ -402,21 +385,21 @@ class WidgetInspector extends JFrame
|
|||||||
return widgetIdMap.get(packedId);
|
return widgetIdMap.get(packedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void open()
|
public void open()
|
||||||
{
|
{
|
||||||
setVisible(true);
|
super.open();
|
||||||
toFront();
|
|
||||||
repaint();
|
|
||||||
overlayManager.add(this.overlay.get());
|
overlayManager.add(this.overlay.get());
|
||||||
clientThread.invokeLater(this::addPickerWidget);
|
clientThread.invokeLater(this::addPickerWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
overlayManager.remove(this.overlay.get());
|
overlayManager.remove(this.overlay.get());
|
||||||
clientThread.invokeLater(this::removePickerWidget);
|
clientThread.invokeLater(this::removePickerWidget);
|
||||||
setSelectedWidget(null, -1, false);
|
setSelectedWidget(null, -1, false);
|
||||||
setVisible(false);
|
super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removePickerWidget()
|
private void removePickerWidget()
|
||||||
|
|||||||
83
runelite-jshell/pom.xml
Normal file
83
runelite-jshell/pom.xml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (c) 2016-2017, 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>net.runelite</groupId>
|
||||||
|
<artifactId>runelite-parent</artifactId>
|
||||||
|
<version>1.7.2-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>jshell</artifactId>
|
||||||
|
<name>RuneLite JShell</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject</groupId>
|
||||||
|
<artifactId>guice</artifactId>
|
||||||
|
<classifier>no_aop</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.findbugs</groupId>
|
||||||
|
<artifactId>jsr305</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fifesoft</groupId>
|
||||||
|
<artifactId>rsyntaxtextarea</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fifesoft</groupId>
|
||||||
|
<artifactId>autocomplete</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>11</source>
|
||||||
|
<target>11</target>
|
||||||
|
<release>11</release>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -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 "RLShell";
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 RuneLite 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);
|
||||||
|
|
||||||
Reference in New Issue
Block a user