package com.kit.plugins.skills.mining; import com.google.common.primitives.Shorts; import com.kit.Application; import com.kit.api.event.MessageEvent; import com.kit.api.plugin.Option; import com.kit.api.plugin.Schedule; import com.kit.api.util.PaintUtils; import com.kit.Application; import com.kit.api.collection.Filter; import com.kit.api.event.EventHandler; import com.kit.api.event.MessageEvent; import com.kit.api.event.PaintEvent; import com.kit.api.overlay.BoxOverlay; import com.kit.api.plugin.Option; import com.kit.api.plugin.Plugin; import com.kit.api.plugin.Schedule; import com.kit.api.util.ColorUtils; import com.kit.api.util.PaintUtils; import com.kit.api.wrappers.GameObject; import com.kit.api.wrappers.GameObjectType; import com.kit.core.control.PluginManager; import java.awt.*; import java.util.*; import java.util.List; import java.util.stream.Collectors; /** */ public class MiningOverlayPlugin extends Plugin { private static final int WOODCUTTING_ANIMATION = 2846; private static final int[] PICKAXE_IDS = Arrays.stream(PickaxeType.values()).mapToInt(PickaxeType::getId).toArray(); private final Font FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 14); private final MiningBoxOverlay box = new MiningBoxOverlay(this); @Option(label = "Show clay rocks", type = Option.Type.TOGGLE, value = "true") private boolean showClay; @Option(label = "Show copper rocks", type = Option.Type.TOGGLE, value = "true") private boolean showCopper; @Option(label = "Show tin rocks", type = Option.Type.TOGGLE, value = "true") private boolean showTin; @Option(label = "Show iron rocks", type = Option.Type.TOGGLE, value = "true") private boolean showIron; @Option(label = "Show silver rocks", type = Option.Type.TOGGLE, value = "true") private boolean showSilver; @Option(label = "Show coal rocks", type = Option.Type.TOGGLE, value = "true") private boolean showCoal; @Option(label = "Show gold rocks", type = Option.Type.TOGGLE, value = "true") private boolean showGold; @Option(label = "Show mithril rocks", type = Option.Type.TOGGLE, value = "true") private boolean showMithril; @Option(label = "Show adamntite rocks", type = Option.Type.TOGGLE, value = "true") private boolean showAdamntite; @Option(label = "Show runite rocks", type = Option.Type.TOGGLE, value = "true") private boolean showRunite; @Option(label = "Draw rocks on minimap", type = Option.Type.TOGGLE, value = "true") private boolean showOnMinimap; @Option(label = "Draw rocks on screen", type = Option.Type.TOGGLE, value = "true") private boolean showOnScreen; @Option(label = "Highlight nearest matching rock", type = Option.Type.TOGGLE, value = "true") private boolean highlightRock; @Option(label = "Floating overlay", value = "false", type = Option.Type.TOGGLE) private boolean floating; private Filter<GameObject> filter; private List<GameObject> rocks; private long lastYield; private long sampleStart; private int sampleOresMined; private int oresMined = 0; private float opacityMultiplier = 0.01f; private boolean opacityUp = true; private int opacityRate = 0; private Map<Short, String> nameForColorMap = new HashMap<>(); private boolean active; public MiningOverlayPlugin(PluginManager manager) { super(manager); } @Override public String getName() { return "Mining"; } @Override public String getGroup() { return "Skills"; } @Override public void start() { ui.registerBoxOverlay(box); } @Override public void stop() { ui.deregisterBoxOverlay(box); } @Schedule(1000) public void checkState() { if (System.currentTimeMillis() - lastYield >= 300000) { // If we've chopped nothing in the last 5 minutes reset the sample rate. sampleOresMined = 0; } if (!isLoggedIn()) { return; } rocks = objects.find() .type(GameObjectType.INTERACTABLE) .hasAction("Mine") .distance(17) .filter(filter) .asList() .stream() .sorted(Comparator.comparingInt(x -> x.distanceTo(player))) .collect(Collectors.toList()); active = inventory.contains(PICKAXE_IDS) || equipment.contains(PICKAXE_IDS); } @EventHandler public void onPaint(PaintEvent e) { if (!isLoggedIn() || rocks == null || !active || bank.isOpen()) { return; } Graphics2D g = (Graphics2D) e.getGraphics().create(); int idx = 0; for (GameObject rock : rocks) { if (rock.unwrap() == null) { continue; } if (showOnScreen) { Point basePoint = rock.getBasePoint(); if (highlightRock && idx == 0 && rock.getModel().isValid()) { g.setColor(new Color(255, 255, 0, (int) (150 * opacityMultiplier))); rock.getModel().fill(g); } if (basePoint.x != -1 && basePoint.y != -1) { g.setColor(Application.COLOUR_SCHEME.getText()); g.setFont(FONT); PaintUtils.drawString(g, getNameForRock(rock), basePoint.x, basePoint.y); } } if (showOnMinimap) { Point minimapPoint = minimap.convert(rock.getTile()); if (minimapPoint.x != -1 && minimapPoint.y != -1) { g.setColor(Color.CYAN); g.setFont(FONT.deriveFont(10f)); PaintUtils.drawString(g, getNameForRock(rock), minimapPoint.x, minimapPoint.y); } } idx++; } opacityRate++; if (opacityRate == 100) { opacityUp = !opacityUp; opacityRate = 0; } if (opacityUp) { opacityMultiplier += 0.01f; } else { opacityMultiplier -= 0.01f; } g.dispose(); } @EventHandler public void onMessageEvent(MessageEvent event) { if (event.getMessage().contains("You manage to mine")) { lastYield = System.currentTimeMillis(); oresMined++; if (sampleOresMined == 0) { sampleStart = System.currentTimeMillis(); } sampleOresMined++; } } @Override public void onOptionsChanged() { RockType.CLAY.setShow(showClay); RockType.COPPER.setShow(showCopper); RockType.TIN.setShow(showTin); RockType.IRON.setShow(showIron); RockType.SILVER.setShow(showSilver); RockType.COAL.setShow(showCoal); RockType.GOLD.setShow(showGold); RockType.MITHRIL.setShow(showMithril); RockType.ADAMANTITE.setShow(showAdamntite); RockType.RUNITE.setShow(showRunite); List<Short> colors = new ArrayList<>(); for (RockType r : RockType.values()) { if (r.isShow()) { colors.addAll(Shorts.asList(r.getColors())); } } filter = acceptable -> acceptable.getComposite() != null && Arrays.asList(acceptable.getComposite().getOriginalModelColors()) .stream().anyMatch(shorts -> { if (shorts == null) { return false; } for (short color : shorts) { if (colors.contains(color)) { return true; } } return false; }); } private String getNameForRock(GameObject object) { if (object.getComposite() == null) { return null; } for (short color : object.getComposite().getOriginalModelColors()) { String name = getNameForColor(color); if (name != null) { return name; } } return null; } private String getNameForColor(short color) { if (nameForColorMap.containsKey(color)) { return nameForColorMap.get(color); } for (RockType type : RockType.values()) { for (short color_ : type.getColors()) { if (color_ == color) { nameForColorMap.put(color, type.getName()); return type.getName(); } } } return null; } private class MiningBoxOverlay extends BoxOverlay { private final Color BACKGROUND_COLOR = ColorUtils.setOpacity(new Color(75, 67, 54, 255), 200); private final Font FONT = new Font(Font.SANS_SERIF, Font.BOLD, 9); protected MiningBoxOverlay(Plugin owner) { super(owner); setFloating(floating); } @Override public void draw(Graphics2D gfx) { gfx.setColor(BACKGROUND_COLOR); gfx.fillRect(0, 0, getWidth(), getHeight()); gfx.setColor(Application.COLOUR_SCHEME.getText()); gfx.setFont(FONT); PaintUtils.drawString(gfx, "Mining", 10, 15); gfx.drawLine(10, 20, getWidth() - 10, 20); gfx.setFont(FONT); int oresMinedWidth = gfx.getFontMetrics().stringWidth("Ores mined:"); PaintUtils.drawString(gfx, "Ores mined:", 10, 35); gfx.setFont(FONT.deriveFont(Font.PLAIN)); PaintUtils.drawString(gfx, String.valueOf(oresMined), oresMinedWidth + 20, 35); gfx.setFont(FONT); int oresPerHrWidth = gfx.getFontMetrics().stringWidth("Ores/hr:"); PaintUtils.drawString(gfx, "Ores/hr:", 10, 50); gfx.setFont(FONT.deriveFont(Font.PLAIN)); if (sampleOresMined > 0) { double timePerOre = (System.currentTimeMillis() - sampleStart) / sampleOresMined; int oresPerHour = (int) (3600000D / timePerOre); PaintUtils.drawString(gfx, String.valueOf(oresPerHour), oresPerHrWidth + 20, 50); } else { PaintUtils.drawString(gfx, "N/A", oresPerHrWidth + 20, 50); } // Draw the box outline gfx.setColor(new Color(0, 0, 0)); gfx.drawRect(0, 0, getWidth() - 1, getHeight() - 1); } @Override public DockPosition getDockPosition() { return DockPosition.LEFT; } @Override public int getWidth() { return 120; } @Override public int getHeight() { return 70; } @Override public boolean isShowing() { return isLoggedIn() && active && !bank.isOpen(); } @Override public void setFloating(boolean floating) { MiningOverlayPlugin.this.floating = floating; MiningOverlayPlugin.this.persistOptions(); super.setFloating(floating); } } }