diff --git a/runelite-client/.gitignore b/runelite-client/.gitignore new file mode 100644 index 0000000000..a6f89c2da7 --- /dev/null +++ b/runelite-client/.gitignore @@ -0,0 +1 @@ +/target/ \ No newline at end of file diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml new file mode 100644 index 0000000000..aac069cc65 --- /dev/null +++ b/runelite-client/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + net.runelite + client + 1.0.0-SNAPSHOT + + + UTF-8 + 1.8 + 1.8 + + 113-SNAPSHOT + + 1.7.12 + + + + + runelite + ${runelite.repository.url} + + + + + + runelite + RuneLite + http://repo.runelite.net + + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-simple + ${slf4j.version} + + + net.sf.jopt-simple + jopt-simple + 5.0.1 + + + + net.runelite.rs + api + 1.0.0-SNAPSHOT + + + net.runelite.rs + client + ${rs.version} + + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.wagon + wagon-ssh + 2.10 + + + + \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ClientLoader.java b/runelite-client/src/main/java/net/runelite/client/ClientLoader.java new file mode 100644 index 0000000000..09e1ea8b36 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ClientLoader.java @@ -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; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ConfigLoader.java b/runelite-client/src/main/java/net/runelite/client/ConfigLoader.java new file mode 100644 index 0000000000..a9f831c3da --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ConfigLoader.java @@ -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 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 getProperties() + { + return properties; + } + + public String getAppletProperty(String name) + { + return appletProperties.get(name); + } + + public Map getAppletProperties() + { + return appletProperties; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/RSStub.java b/runelite-client/src/main/java/net/runelite/client/RSStub.java new file mode 100644 index 0000000000..efc0287da4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/RSStub.java @@ -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); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java new file mode 100644 index 0000000000..b737cb1b1f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -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; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java new file mode 100644 index 0000000000..6005ce6e2b --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/Plugin.java @@ -0,0 +1,8 @@ +package net.runelite.client.plugins; + +import net.runelite.client.ui.overlay.Overlay; + +public abstract class Plugin +{ + public abstract Overlay getOverlay(); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java new file mode 100644 index 0000000000..7ff8e0e614 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -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 plugins = new ArrayList<>(); + + public void loadAll() + { + plugins.add(new Boosts()); + plugins.add(new OpponentInfo()); + } + + public Collection getPlugins() + { + return plugins; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java new file mode 100644 index 0000000000..040c582a88 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/Boosts.java @@ -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; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java new file mode 100644 index 0000000000..f536d7078c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java @@ -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); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java new file mode 100644 index 0000000000..23ae1a099f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java @@ -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; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java new file mode 100644 index 0000000000..3bc22c3f63 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java @@ -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); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java new file mode 100644 index 0000000000..5c613aece6 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientPanel.java @@ -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) + { + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java new file mode 100644 index 0000000000..ee927145b3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -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) + { + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java new file mode 100644 index 0000000000..ae65f34d8f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java @@ -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); +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java new file mode 100644 index 0000000000..accd8ff3e3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java @@ -0,0 +1,6 @@ +package net.runelite.client.ui.overlay; + +public enum OverlayPosition +{ + TOP_LEFT; +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPriority.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPriority.java new file mode 100644 index 0000000000..cd6253e907 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPriority.java @@ -0,0 +1,8 @@ +package net.runelite.client.ui.overlay; + +public enum OverlayPriority +{ + LOW, + MED, + HIGH; +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java new file mode 100644 index 0000000000..420b4c5d51 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -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); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/TopDownRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/TopDownRenderer.java new file mode 100644 index 0000000000..22ed9d2c1e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/TopDownRenderer.java @@ -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 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; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java b/runelite-client/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java new file mode 100644 index 0000000000..f15a40e029 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java @@ -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(); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/ConfigLoaderTest.java b/runelite-client/src/test/java/net/runelite/client/ConfigLoaderTest.java new file mode 100644 index 0000000000..ba34ce18b4 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/ConfigLoaderTest.java @@ -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)); + } + +}