Add 'runelite-client/' from commit '235c44e5253d81e269433c286d9c923e4a06c51f'

git-subtree-dir: runelite-client
git-subtree-mainline: eea98253efa42e378543ad7d7b167a954e2e041c
git-subtree-split: 235c44e525
This commit is contained in:
Adam
2016-04-25 18:53:09 -04:00
21 changed files with 909 additions and 0 deletions

1
runelite-client/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target/

79
runelite-client/pom.xml Normal file
View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>net.runelite</groupId>
<artifactId>client</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<rs.version>113-SNAPSHOT</rs.version>
<slf4j.version>1.7.12</slf4j.version>
</properties>
<distributionManagement>
<repository>
<id>runelite</id>
<url>${runelite.repository.url}</url>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>runelite</id>
<name>RuneLite</name>
<url>http://repo.runelite.net</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>net.runelite.rs</groupId>
<artifactId>api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>net.runelite.rs</groupId>
<artifactId>client</artifactId>
<version>${rs.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.10</version>
</extension>
</extensions>
</build>
</project>

View File

@@ -0,0 +1,28 @@
package net.runelite.client;
import java.applet.Applet;
import java.io.IOException;
import java.net.MalformedURLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientLoader
{
private static final Logger logger = LoggerFactory.getLogger(ClientLoader.class);
public Applet load() throws MalformedURLException, ClassNotFoundException, IOException, InstantiationException, IllegalAccessException
{
ConfigLoader config = new ConfigLoader();
config.fetch();
String initialClass = config.getProperty(ConfigLoader.INITIAL_CLASS).replace(".class", "");
Class<?> clientClass = this.getClass().getClassLoader().loadClass(initialClass);
Applet rs = (Applet) clientClass.newInstance();
rs.setStub(new RSStub(config, rs));
return rs;
}
}

View File

@@ -0,0 +1,92 @@
package net.runelite.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
public class ConfigLoader
{
private static URL configURL;
public static final String CODEBASE = "codebase";
public static final String INITIAL_JAR = "initial_jar";
public static final String INITIAL_CLASS = "initial_class";
public static final String APP_MINWIDTH = "applet_minwidth";
public static final String APP_MINHEIGHT = "applet_minheight";
private final Map<String, String> properties = new HashMap<>(),
appletProperties = new HashMap<>();
static
{
try
{
configURL = new URL("http://oldschool.runescape.com/jav_config.ws"); // https redirects us to rs3
}
catch (MalformedURLException ex)
{
ex.printStackTrace();
}
}
public void fetch() throws IOException
{
URLConnection conn = configURL.openConnection();
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())))
{
String str;
while ((str = in.readLine()) != null)
{
int idx = str.indexOf('=');
if (idx == -1)
continue;
String s = str.substring(0, idx);
if (s.equals("param"))
{
str = str.substring(idx + 1);
idx = str.indexOf('=');
s = str.substring(0, idx);
appletProperties.put(s, str.substring(idx + 1));
}
else if (s.equals("msg"))
{
// ignore
}
else
{
properties.put(s, str.substring(idx + 1));
}
}
}
}
public String getProperty(String name)
{
return properties.get(name);
}
public Map<String, String> getProperties()
{
return properties;
}
public String getAppletProperty(String name)
{
return appletProperties.get(name);
}
public Map<String, String> getAppletProperties()
{
return appletProperties;
}
}

View File

@@ -0,0 +1,67 @@
package net.runelite.client;
import java.applet.Applet;
import java.applet.AppletContext;
import java.applet.AppletStub;
import java.awt.Dimension;
import java.net.MalformedURLException;
import java.net.URL;
public class RSStub implements AppletStub
{
private final ConfigLoader config;
private final Applet app;
public RSStub(ConfigLoader config, Applet app)
{
this.config = config;
this.app = app;
}
@Override
public boolean isActive()
{
return true;
}
@Override
public URL getDocumentBase()
{
return getCodeBase();
}
@Override
public URL getCodeBase()
{
try
{
return new URL(config.getProperty(ConfigLoader.CODEBASE));
}
catch (MalformedURLException ex)
{
return null;
}
}
@Override
public String getParameter(String name)
{
return config.getAppletProperty(name);
}
@Override
public AppletContext getAppletContext()
{
return null;
}
@Override
public void appletResize(int width, int height)
{
Dimension d = new Dimension(width, height);
app.setSize(d);
app.setPreferredSize(d);
}
}

View File

@@ -0,0 +1,75 @@
package net.runelite.client;
import java.io.File;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import net.runelite.api.Client;
import net.runelite.client.plugins.PluginManager;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.overlay.OverlayRenderer;
public class RuneLite
{
public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite");
public static final File REPO_DIR = new File(RUNELITE_DIR, "repository");
private static OptionSet options;
private static Client client;
private static RuneLite runelite;
private ClientUI gui;
private PluginManager pluginManager;
private OverlayRenderer renderer;
public static void main(String[] args) throws Exception
{
OptionParser parser = new OptionParser();
parser.accepts("developer-mode");
options = parser.parse(args);
runelite = new RuneLite();
runelite.start();
}
public void start() throws Exception
{
gui = new ClientUI();
gui.setVisible(true);
pluginManager = new PluginManager();
pluginManager.loadAll();
renderer = new OverlayRenderer();
}
public static Client getClient()
{
return client;
}
public static void setClient(Client client)
{
RuneLite.client = client;
}
public static RuneLite getRunelite()
{
return runelite;
}
public PluginManager getPluginManager()
{
return pluginManager;
}
public OverlayRenderer getRenderer()
{
return renderer;
}
public static OptionSet getOptions()
{
return options;
}
}

View File

@@ -0,0 +1,8 @@
package net.runelite.client.plugins;
import net.runelite.client.ui.overlay.Overlay;
public abstract class Plugin
{
public abstract Overlay getOverlay();
}

View File

@@ -0,0 +1,23 @@
package net.runelite.client.plugins;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.runelite.client.plugins.boosts.Boosts;
import net.runelite.client.plugins.opponentinfo.OpponentInfo;
public class PluginManager
{
private final List<Plugin> plugins = new ArrayList<>();
public void loadAll()
{
plugins.add(new Boosts());
plugins.add(new OpponentInfo());
}
public Collection<Plugin> getPlugins()
{
return plugins;
}
}

View File

@@ -0,0 +1,15 @@
package net.runelite.client.plugins.boosts;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.Overlay;
public class Boosts extends Plugin
{
private final Overlay overlay = new BoostsOverlay();
@Override
public Overlay getOverlay()
{
return overlay;
}
}

View File

@@ -0,0 +1,86 @@
package net.runelite.client.plugins.boosts;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.Skill;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
class BoostsOverlay extends Overlay
{
private static final int WIDTH = 140;
private static final Color BACKGROUND = new Color(Color.gray.getRed(), Color.gray.getGreen(), Color.gray.getBlue(), 127);
private static final Skill[] SHOW = new Skill[] { Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE, Skill.RANGED, Skill.MAGIC };
private static final int TOP_BORDER = 2;
private static final int LEFT_BORDER = 2;
private static final int RIGHT_BORDER = 2;
private static final int SEPARATOR = 2;
BoostsOverlay()
{
super(OverlayPosition.TOP_LEFT, OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
Client client = RuneLite.getClient();
if (client.getGameState() != GameState.LOGGED_IN)
return null;
FontMetrics metrics = graphics.getFontMetrics();
int[] boostedSkills = client.getBoostedSkillLevels(),
baseSkills = client.getRealSkillLevels();
int height = TOP_BORDER;
for (Skill skill : SHOW)
{
int boosted = boostedSkills[skill.ordinal()],
base = baseSkills[skill.ordinal()];
if (boosted == base)
continue;
height += metrics.getHeight() + SEPARATOR;
}
if (height == TOP_BORDER)
return null;
graphics.setColor(BACKGROUND);
graphics.fillRect(0, 0, WIDTH, height);
int y = TOP_BORDER;
for (Skill skill : SHOW)
{
int boosted = boostedSkills[skill.ordinal()],
base = baseSkills[skill.ordinal()];
if (boosted == base)
continue;
graphics.setColor(Color.white);
graphics.drawString(skill.getName(), LEFT_BORDER, y + metrics.getHeight());
String str = boosted + "/" + base;
graphics.drawString(str, WIDTH - RIGHT_BORDER - metrics.stringWidth(str), y + metrics.getHeight());
y += metrics.getHeight() + SEPARATOR;
}
return new Dimension(WIDTH, height);
}
}

View File

@@ -0,0 +1,15 @@
package net.runelite.client.plugins.opponentinfo;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.Overlay;
public class OpponentInfo extends Plugin
{
private final Overlay overlay = new OpponentInfoOverlay();
@Override
public Overlay getOverlay()
{
return overlay;
}
}

View File

@@ -0,0 +1,99 @@
package net.runelite.client.plugins.opponentinfo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
class OpponentInfoOverlay extends Overlay
{
private static final int WIDTH = 140;
private static final int TOP_BORDER = 2;
private static final int BOTTOM_BORDER = 2;
private static final int BAR_WIDTH = 124;
private static final int BAR_HEIGHT = 20;
private static final Color BACKGROUND = new Color(Color.gray.getRed(), Color.gray.getGreen(), Color.gray.getBlue(), 127);
private static final Color HP_GREEN = new Color(0, 146, 54, 230);
private static final Color HP_RED = new Color(102, 15, 16, 230);
OpponentInfoOverlay()
{
super(OverlayPosition.TOP_LEFT, OverlayPriority.HIGH);
}
private Actor getOpponent()
{
Client client = RuneLite.getClient();
Player player = client.getLocalPlayer();
if (player == null)
return null;
return player.getInteracting();
}
@Override
public Dimension render(Graphics2D graphics)
{
Actor opponent = getOpponent();
if (opponent == null)
return null;
int cur = opponent.getHealth();
int max = opponent.getMaxHealth();
FontMetrics fm = graphics.getFontMetrics();
int height = TOP_BORDER
+ fm.getHeight(); // opponent name
if (max > 0)
height += 1 // between name and hp bar
+ BAR_HEIGHT; // bar
height += BOTTOM_BORDER;
graphics.setColor(BACKGROUND);
graphics.fillRect(0, 0, WIDTH, height);
String str = opponent.getName();
int x = (WIDTH - fm.stringWidth(str)) / 2;
graphics.setColor(Color.white);
graphics.drawString(str, x, fm.getHeight() + TOP_BORDER);
// hp bar
if (max > 0)
{
float percent = (float) cur / (float) max;
if (percent > 100f)
percent = 100f;
int barWidth = (int) (percent * (float) BAR_WIDTH);
int barY = TOP_BORDER + fm.getHeight() + 1;
graphics.setColor(HP_GREEN);
graphics.fillRect((WIDTH - BAR_WIDTH) / 2, barY, barWidth, BAR_HEIGHT);
graphics.setColor(HP_RED);
graphics.fillRect(((WIDTH - BAR_WIDTH) / 2) + barWidth, barY, BAR_WIDTH - barWidth, BAR_HEIGHT);
str = cur + " / " + max;
x = (WIDTH - fm.stringWidth(str)) / 2;
graphics.setColor(Color.white);
graphics.drawString(str, x, barY + fm.getHeight());
}
return new Dimension(WIDTH, height);
}
}

View File

@@ -0,0 +1,60 @@
package net.runelite.client.ui;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JPanel;
import net.runelite.api.Client;
import net.runelite.client.ClientLoader;
import net.runelite.client.RuneLite;
final class ClientPanel extends JPanel implements ComponentListener
{
public static final int PANEL_WIDTH = 765, PANEL_HEIGHT = 503;
private Applet rs;
public ClientPanel() throws Exception
{
setSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setMinimumSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setBackground(Color.black);
this.addComponentListener(this);
ClientLoader loader = new ClientLoader();
rs = loader.load();
rs.setSize(this.getSize());
rs.init();
rs.start();
this.add(rs);
RuneLite.setClient(new Client((net.runelite.rs.api.Client) rs));
}
@Override
public void componentResized(ComponentEvent e)
{
rs.setSize(this.getSize());
this.setPreferredSize(this.getSize());
rs.setPreferredSize(this.getPreferredSize());
}
@Override
public void componentMoved(ComponentEvent e)
{
}
@Override
public void componentShown(ComponentEvent e)
{
}
@Override
public void componentHidden(ComponentEvent e)
{
}
}

View File

@@ -0,0 +1,85 @@
package net.runelite.client.ui;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public final class ClientUI extends JFrame implements ComponentListener
{
private ClientPanel panel;
public ClientUI() throws Exception
{
init();
pack();
setTitle("RuneLite");
setLocationRelativeTo(getOwner());
setMinimumSize(getSize());
setResizable(true);
this.addComponentListener(this);
}
private void init() throws Exception
{
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
checkExit();
}
});
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ignored)
{
}
panel = new ClientPanel();
add(panel);
}
private void checkExit()
{
int result = JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?", "Exit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.OK_OPTION)
{
System.exit(0);
}
}
@Override
public void componentResized(ComponentEvent e)
{
SwingUtilities.invokeLater(() -> pack()); // is this right?
}
@Override
public void componentMoved(ComponentEvent e)
{
}
@Override
public void componentShown(ComponentEvent e)
{
}
@Override
public void componentHidden(ComponentEvent e)
{
}
}

View File

@@ -0,0 +1,38 @@
package net.runelite.client.ui.overlay;
import java.awt.Dimension;
import java.awt.Graphics2D;
public abstract class Overlay
{
private OverlayPosition position; // where to draw it
private OverlayPriority priority; // if multiple overlays exist in the same position, who wins
public Overlay(OverlayPosition position, OverlayPriority priority)
{
this.position = position;
this.priority = priority;
}
public OverlayPosition getPosition()
{
return position;
}
public void setPosition(OverlayPosition position)
{
this.position = position;
}
public OverlayPriority getPriority()
{
return priority;
}
public void setPriority(OverlayPriority priority)
{
this.priority = priority;
}
public abstract Dimension render(Graphics2D graphics);
}

View File

@@ -0,0 +1,6 @@
package net.runelite.client.ui.overlay;
public enum OverlayPosition
{
TOP_LEFT;
}

View File

@@ -0,0 +1,8 @@
package net.runelite.client.ui.overlay;
public enum OverlayPriority
{
LOW,
MED,
HIGH;
}

View File

@@ -0,0 +1,23 @@
package net.runelite.client.ui.overlay;
import java.awt.image.BufferedImage;
import net.runelite.client.RuneLite;
import net.runelite.client.plugins.Plugin;
public class OverlayRenderer
{
public void render(BufferedImage clientBuffer)
{
TopDownRenderer td = new TopDownRenderer();
for (Plugin plugin : RuneLite.getRunelite().getPluginManager().getPlugins())
{
Overlay overlay = plugin.getOverlay();
if (overlay.getPosition() == OverlayPosition.TOP_LEFT)
td.add(overlay);
}
td.render(clientBuffer);
}
}

View File

@@ -0,0 +1,40 @@
package net.runelite.client.ui.overlay;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
public class TopDownRenderer
{
private static final int BORDER_TOP = 25;
private static final int BORDER_LEFT = 10;
private static final int PADDING = 10;
private final List<Overlay> overlays = new ArrayList<>();
public void add(Overlay overlay)
{
overlays.add(overlay);
}
public void render(BufferedImage clientBuffer)
{
overlays.sort((o1, o2) -> o2.getPriority().compareTo(o1.getPriority()));
int y = BORDER_TOP;
for (Overlay overlay : overlays)
{
BufferedImage image = clientBuffer.getSubimage(BORDER_LEFT, y, clientBuffer.getWidth() - BORDER_LEFT, clientBuffer.getHeight() - y);//(int) dimension.getWidth(), (int) dimension.getHeight());
Graphics2D graphics = image.createGraphics();
Dimension dimension = overlay.render(graphics);
graphics.dispose();
if (dimension == null)
continue;
y += dimension.getHeight() + PADDING;
}
}
}

View File

@@ -0,0 +1,34 @@
package net.runelite.inject.callbacks;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.overlay.OverlayRenderer;
public class RSCanvasCallback
{
private final BufferedImage clientBuffer = new BufferedImage(765, 503, BufferedImage.TYPE_INT_RGB);
private final BufferedImage gameBuffer = new BufferedImage(765, 503, BufferedImage.TYPE_INT_RGB);
public Graphics getGraphics(Canvas canvas, Graphics superGraphics)
{
Graphics clientGraphics = clientBuffer.getGraphics();
clientGraphics.drawImage(gameBuffer, 0, 0, null);
clientGraphics.dispose();
RuneLite runelite = RuneLite.getRunelite();
if (runelite != null)
{
OverlayRenderer renderer = runelite.getRenderer();
if (renderer != null)
{
renderer.render(clientBuffer);
}
}
superGraphics.drawImage(clientBuffer, 0, 0, null);
return gameBuffer.getGraphics();
}
}

View File

@@ -0,0 +1,27 @@
package net.runelite.client;
import java.io.IOException;
import org.junit.Test;
/**
*
* @author Adam
*/
public class ConfigLoaderTest
{
@Test
public void test() throws IOException
{
ConfigLoader loader = new ConfigLoader();
loader.fetch();
for (String key : loader.getProperties().keySet())
System.out.println(key + ": " + loader.getProperty(key));
System.out.println("Applet properties:");
for (String key : loader.getAppletProperties().keySet())
System.out.println(key + ": " + loader.getAppletProperty(key));
}
}