diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java
index 557bc675b1..f01c70a946 100644
--- a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java
+++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java
@@ -38,6 +38,7 @@ public class RuneLiteProperties
{
private static final String RUNELITE_TITLE = "runelite.title";
private static final String RUNELITE_VERSION = "runelite.version";
+ private static final String RUNESCAPE_VERSION = "runescape.version";
private final Properties properties = new Properties();
@@ -64,4 +65,9 @@ public class RuneLiteProperties
{
return properties.getProperty(RUNELITE_VERSION);
}
+
+ public String getRunescapeVersion()
+ {
+ return properties.getProperty(RUNESCAPE_VERSION);
+ }
}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java
new file mode 100644
index 0000000000..e58c12c5f6
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2018 Abex
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.runelite.client.plugins.info;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+import java.awt.Font;
+import com.google.inject.Inject;
+import java.util.concurrent.ScheduledExecutorService;
+import javax.annotation.Nullable;
+import javax.swing.GroupLayout;
+import javax.swing.JLabel;
+import javax.swing.LayoutStyle;
+import javax.swing.event.HyperlinkEvent;
+import lombok.extern.slf4j.Slf4j;
+import net.runelite.api.Client;
+import net.runelite.api.events.SessionClose;
+import net.runelite.api.events.SessionOpen;
+import net.runelite.client.RuneLiteProperties;
+import net.runelite.client.account.SessionManager;
+import net.runelite.client.ui.FontManager;
+import net.runelite.client.ui.PluginPanel;
+import net.runelite.client.util.RunnableExceptionLogger;
+
+@Slf4j
+public class InfoPanel extends PluginPanel
+{
+ private final static String RUNELITE_LOGIN = "https://runelite_login/";
+
+ @Inject
+ @Nullable
+ private Client client;
+
+ @Inject
+ private RuneLiteProperties runeLiteProperties;
+
+ @Inject
+ private EventBus eventBus;
+
+ @Inject
+ private SessionManager sessionManager;
+
+ @Inject
+ private ScheduledExecutorService executor;
+
+ private final GroupLayout layout = new GroupLayout(this);
+
+ private final JLabel usernameHeader = new JLabel();
+ private final JRichTextPane username = new JRichTextPane();
+
+ void init()
+ {
+ setLayout(layout);
+
+ final Font smallFont = FontManager.getRunescapeSmallFont();
+
+ final JLabel runeliteVersionHeader = new JLabel("RuneLite version");
+ runeliteVersionHeader.setFont(smallFont);
+ final JLabel runeliteVersion = new JLabel(runeLiteProperties.getVersion());
+
+ final JLabel runescapeVersionHeader = new JLabel("OldSchool Engine");
+ runescapeVersionHeader.setFont(smallFont);
+
+ String engineVer = "Unknown";
+ if (client != null)
+ {
+ engineVer = String.format("Rev %s", runeLiteProperties.getRunescapeVersion());
+ }
+ final JLabel runescapeVersion = new JLabel(engineVer);
+
+ usernameHeader.setFont(smallFont);
+ username.enableAutoLinkHandler(false);
+ username.addHyperlinkListener(e ->
+ {
+ if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null)
+ {
+ if (e.getURL().toString().equals(RUNELITE_LOGIN))
+ {
+ executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
+ }
+ }
+ });
+ setNotLoggedIn();
+
+ final JRichTextPane issueLink = new JRichTextPane("text/html",
+ "RuneLite is open source!
"
+ + "Found an issue? Want a feature?
"
+ + ""
+ + "Open an issue on GitHub!"
+ + ""
+ );
+
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup()
+ .addComponent(runeliteVersionHeader)
+ .addComponent(runescapeVersionHeader)
+ ).addGroup(layout.createParallelGroup()
+ .addComponent(runeliteVersion)
+ .addComponent(runescapeVersion)
+ ).addGap(6)
+ .addComponent(usernameHeader)
+ .addGroup(layout.createParallelGroup()
+ .addComponent(username)
+ )
+ .addGap(12)
+ .addComponent(issueLink)
+ );
+
+ layout.setHorizontalGroup(layout.createParallelGroup()
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(runeliteVersionHeader)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
+ .addComponent(runescapeVersionHeader)
+ ).addGroup(layout.createSequentialGroup()
+ .addComponent(runeliteVersion)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
+ .addComponent(runescapeVersion)
+ )
+ .addComponent(usernameHeader)
+ .addComponent(username)
+ .addComponent(issueLink)
+ );
+
+ eventBus.register(this);
+ }
+
+ private void setNotLoggedIn()
+ {
+ username.setContentType("text/html");
+ username.setText("Login to sync settings to the cloud.");
+ usernameHeader.setText("Not logged in");
+ }
+
+ @Subscribe
+ private void onSessionOpen(SessionOpen sessionOpen)
+ {
+ String name = sessionManager.getAccountSession().getUsername();
+ if (name != null)
+ {
+ username.setContentType("text/plain");
+ username.setText(name);
+ usernameHeader.setText("Logged in as");
+ }
+ }
+
+ @Subscribe
+ private void onSessionClose(SessionClose e)
+ {
+ setNotLoggedIn();
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java
new file mode 100644
index 0000000000..8a1a1163b4
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Abex
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.runelite.client.plugins.info;
+
+import com.google.inject.Binder;
+import javax.imageio.ImageIO;
+import javax.inject.Inject;
+import net.runelite.client.plugins.Plugin;
+import net.runelite.client.plugins.PluginDescriptor;
+import net.runelite.client.ui.ClientUI;
+import net.runelite.client.ui.NavigationButton;
+
+@PluginDescriptor(
+ name = "Info panel plugin",
+ loadWhenOutdated = true
+)
+public class InfoPlugin extends Plugin
+{
+ @Inject
+ private ClientUI ui;
+
+ @Override
+ public void configure(Binder binder)
+ {
+ binder.bind(InfoPanel.class);
+ }
+
+ @Override
+ protected void startUp() throws Exception
+ {
+ final InfoPanel panel = injector.getInstance(InfoPanel.class);
+ panel.init();
+
+ final NavigationButton navButton = new NavigationButton(
+ "Info",
+ ImageIO.read(getClass().getResourceAsStream("info_icon.png")),
+ () -> panel
+ );
+
+ ui.getPluginToolbar().addNavigation(navButton);
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java
new file mode 100644
index 0000000000..21b8f46cd5
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Abex
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.runelite.client.plugins.info;
+
+import java.awt.Desktop;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import javax.swing.BorderFactory;
+import javax.swing.JEditorPane;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.text.html.HTMLEditorKit;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class JRichTextPane extends JEditorPane
+{
+ private HyperlinkListener linkHandler;
+
+ public JRichTextPane()
+ {
+ super();
+ setHighlighter(null);
+ setEditable(false);
+ setOpaque(false);
+ enableAutoLinkHandler(true);
+ setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ HTMLEditorKit ek = (HTMLEditorKit) getEditorKitForContentType("text/html");
+ ek.getStyleSheet().addRule("a {color: #DDDDDD }");
+ }
+
+ public JRichTextPane(String type, String text)
+ {
+ this();
+ setContentType(type);
+ setText(text);
+ }
+
+ public void enableAutoLinkHandler(boolean enable)
+ {
+ if (enable != (linkHandler != null))
+ {
+ if (enable)
+ {
+ linkHandler = e ->
+ {
+ log.info(e.toString());
+ if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null)
+ {
+ if (Desktop.isDesktopSupported())
+ {
+ try
+ {
+ Desktop.getDesktop().browse(e.getURL().toURI());
+ }
+ catch (URISyntaxException | IOException ex)
+ {
+ log.info("Error opening link", ex);
+ }
+ }
+ }
+ };
+ addHyperlinkListener(linkHandler);
+ }
+ else
+ {
+ removeHyperlinkListener(linkHandler);
+ linkHandler = null;
+ }
+ }
+ }
+
+ public boolean getAutoLinkHandlerEnabled()
+ {
+ return linkHandler != null;
+ }
+}
diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/info/info_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/info/info_icon.png
new file mode 100644
index 0000000000..565f2a48b2
Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/info/info_icon.png differ
diff --git a/runelite-client/src/main/resources/net/runelite/client/runelite.properties b/runelite-client/src/main/resources/net/runelite/client/runelite.properties
index b8516ea64c..684a13c581 100644
--- a/runelite-client/src/main/resources/net/runelite/client/runelite.properties
+++ b/runelite-client/src/main/resources/net/runelite/client/runelite.properties
@@ -1,3 +1,3 @@
runelite.title=RuneLite
runelite.version=${project.version}
-
+runescape.version=${rs.version}