diff --git a/src/main/java/net/runelite/client/RuneLite.java b/src/main/java/net/runelite/client/RuneLite.java index 2db7dd9e47..1876db9c93 100644 --- a/src/main/java/net/runelite/client/RuneLite.java +++ b/src/main/java/net/runelite/client/RuneLite.java @@ -6,7 +6,7 @@ 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.OverlayRenderer; +import net.runelite.client.ui.overlay.OverlayRenderer; public class RuneLite diff --git a/src/main/java/net/runelite/client/plugins/Plugin.java b/src/main/java/net/runelite/client/plugins/Plugin.java index 3903781bff..6005ce6e2b 100644 --- a/src/main/java/net/runelite/client/plugins/Plugin.java +++ b/src/main/java/net/runelite/client/plugins/Plugin.java @@ -1,8 +1,8 @@ package net.runelite.client.plugins; -import net.runelite.client.ui.Overlay; +import net.runelite.client.ui.overlay.Overlay; public abstract class Plugin { - public abstract Overlay drawOverlay(); + public abstract Overlay getOverlay(); } diff --git a/src/main/java/net/runelite/client/plugins/PluginManager.java b/src/main/java/net/runelite/client/plugins/PluginManager.java index 60b0561ae5..7ff8e0e614 100644 --- a/src/main/java/net/runelite/client/plugins/PluginManager.java +++ b/src/main/java/net/runelite/client/plugins/PluginManager.java @@ -3,6 +3,7 @@ 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 @@ -11,6 +12,7 @@ public class PluginManager public void loadAll() { + plugins.add(new Boosts()); plugins.add(new OpponentInfo()); } diff --git a/src/main/java/net/runelite/client/plugins/boosts/Boosts.java b/src/main/java/net/runelite/client/plugins/boosts/Boosts.java new file mode 100644 index 0000000000..040c582a88 --- /dev/null +++ b/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/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java b/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java new file mode 100644 index 0000000000..7f18b24936 --- /dev/null +++ b/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java @@ -0,0 +1,81 @@ +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.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(); + 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/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java b/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java index 40ec49bdaf..23ae1a099f 100644 --- a/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java +++ b/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfo.java @@ -1,105 +1,15 @@ package net.runelite.client.plugins.opponentinfo; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import net.runelite.api.Actor; -import net.runelite.api.Client; -import net.runelite.api.Player; -import net.runelite.client.RuneLite; import net.runelite.client.plugins.Plugin; -import net.runelite.client.ui.Overlay; -import net.runelite.client.ui.OverlayPosition; -import net.runelite.client.ui.OverlayPriority; +import net.runelite.client.ui.overlay.Overlay; public class OpponentInfo extends Plugin { - private static final int WIDTH = 140; - private static final int HEIGHT = 75; - - 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); - - private final BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB); - private final Overlay overlay = new Overlay(image, OverlayPosition.TOP_LEFT, OverlayPriority.HIGH); - - private Actor getOpponent() - { - Client client = RuneLite.getClient(); - - Player player = client.getLocalPlayer(); - if (player == null) - return null; - - return player.getInteracting(); - } + private final Overlay overlay = new OpponentInfoOverlay(); @Override - public Overlay drawOverlay() + public Overlay getOverlay() { - Actor opponent = getOpponent(); - - if (opponent == null) - return null; - - int cur = opponent.getHealth(); - int max = opponent.getMaxHealth(); - - Graphics g = image.getGraphics(); - FontMetrics fm = g.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; - - g.setColor(BACKGROUND); - g.fillRect(0, 0, image.getWidth(), height); - - String str = opponent.getName(); - - int x = (image.getWidth() - fm.stringWidth(str)) / 2; - g.setColor(Color.white); - g.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; - - g.setColor(HP_GREEN); - g.fillRect((WIDTH - BAR_WIDTH) / 2, barY, barWidth, BAR_HEIGHT); - - g.setColor(HP_RED); - g.fillRect(((WIDTH - BAR_WIDTH) / 2) + barWidth, barY, BAR_WIDTH - barWidth, BAR_HEIGHT); - - str = cur + " / " + max; - x = (image.getWidth() - fm.stringWidth(str)) / 2; - g.setColor(Color.white); - g.drawString(str, x, barY + fm.getHeight()); - } - - g.dispose(); - - overlay.setDimension(new Dimension(height, image.getWidth())); - return overlay; } } diff --git a/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java b/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoOverlay.java new file mode 100644 index 0000000000..3bc22c3f63 --- /dev/null +++ b/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/src/main/java/net/runelite/client/ui/Overlay.java b/src/main/java/net/runelite/client/ui/Overlay.java deleted file mode 100644 index 1763923856..0000000000 --- a/src/main/java/net/runelite/client/ui/Overlay.java +++ /dev/null @@ -1,59 +0,0 @@ -package net.runelite.client.ui; - -import java.awt.Dimension; -import java.awt.image.BufferedImage; - -public class Overlay -{ - private BufferedImage image; // image to draw - private Dimension dimension; // dimension of visable overlay - private OverlayPosition position; // where to draw it - private OverlayPriority priority; // if multiple overlays exist in the same position, who wins - - public Overlay(BufferedImage image, OverlayPosition position, OverlayPriority priority) - { - this.image = image; - this.position = position; - this.priority = priority; - } - - public BufferedImage getImage() - { - return image; - } - - public void setImage(BufferedImage image) - { - this.image = image; - } - - public Dimension getDimension() - { - return dimension; - } - - public void setDimension(Dimension dimension) - { - this.dimension = dimension; - } - - 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; - } -} diff --git a/src/main/java/net/runelite/client/ui/OverlayPosition.java b/src/main/java/net/runelite/client/ui/OverlayPosition.java deleted file mode 100644 index 45bda4106d..0000000000 --- a/src/main/java/net/runelite/client/ui/OverlayPosition.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.runelite.client.ui; - -public enum OverlayPosition -{ - TOP_LEFT; -} diff --git a/src/main/java/net/runelite/client/ui/OverlayRenderer.java b/src/main/java/net/runelite/client/ui/OverlayRenderer.java deleted file mode 100644 index 80253ad0dc..0000000000 --- a/src/main/java/net/runelite/client/ui/OverlayRenderer.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.runelite.client.ui; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import net.runelite.client.RuneLite; -import net.runelite.client.plugins.Plugin; - -public class OverlayRenderer -{ - private static final int TOP_LEFT_BORDER_TOP = 25; - private static final int TOP_LEFT_BORDER_LEFT = 10; - private static final int TOP_LEFT_PADDING = 10; - - public void render(Graphics graphics) - { - List overlays = new ArrayList<>(); - - for (Plugin plugin : RuneLite.getRunelite().getPluginManager().getPlugins()) - { - Overlay overlay = plugin.drawOverlay(); - if (overlay != null) - overlays.add(overlay); - } - - Overlay[] topLeft = overlays.stream().filter(o -> o.getPosition() == OverlayPosition.TOP_LEFT).sorted((o1, o2) -> o1.getPriority().compareTo(o2.getPriority())).toArray(s -> new Overlay[s]); - int y = TOP_LEFT_BORDER_TOP; - - for (Overlay overlay : topLeft) - { - BufferedImage image = overlay.getImage(); - Dimension dimension = overlay.getDimension(); - - graphics.drawImage(image, TOP_LEFT_BORDER_LEFT, y, null); - y += dimension.getHeight() + TOP_LEFT_PADDING; - } - } -} diff --git a/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/src/main/java/net/runelite/client/ui/overlay/Overlay.java new file mode 100644 index 0000000000..ae65f34d8f --- /dev/null +++ b/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/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java b/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java new file mode 100644 index 0000000000..accd8ff3e3 --- /dev/null +++ b/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/src/main/java/net/runelite/client/ui/OverlayPriority.java b/src/main/java/net/runelite/client/ui/overlay/OverlayPriority.java similarity index 56% rename from src/main/java/net/runelite/client/ui/OverlayPriority.java rename to src/main/java/net/runelite/client/ui/overlay/OverlayPriority.java index f00b3acdf5..cd6253e907 100644 --- a/src/main/java/net/runelite/client/ui/OverlayPriority.java +++ b/src/main/java/net/runelite/client/ui/overlay/OverlayPriority.java @@ -1,4 +1,4 @@ -package net.runelite.client.ui; +package net.runelite.client.ui.overlay; public enum OverlayPriority { diff --git a/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java new file mode 100644 index 0000000000..420b4c5d51 --- /dev/null +++ b/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/src/main/java/net/runelite/client/ui/overlay/TopDownRenderer.java b/src/main/java/net/runelite/client/ui/overlay/TopDownRenderer.java new file mode 100644 index 0000000000..22ed9d2c1e --- /dev/null +++ b/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/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java b/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java index 1690db94a7..f15a40e029 100644 --- a/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java +++ b/src/main/java/net/runelite/inject/callbacks/RSCanvasCallback.java @@ -4,28 +4,29 @@ import java.awt.Canvas; import java.awt.Graphics; import java.awt.image.BufferedImage; import net.runelite.client.RuneLite; -import net.runelite.client.ui.OverlayRenderer; +import net.runelite.client.ui.overlay.OverlayRenderer; public class RSCanvasCallback { - private final BufferedImage clientBuffer = new BufferedImage(756, 503, BufferedImage.TYPE_INT_RGB); - private final BufferedImage gameBuffer = new BufferedImage(756, 503, BufferedImage.TYPE_INT_RGB); + 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(clientGraphics); + { + renderer.render(clientBuffer); + } } - clientGraphics.dispose(); - superGraphics.drawImage(clientBuffer, 0, 0, null); return gameBuffer.getGraphics();