liverare Posted September 23, 2017 Share Posted September 23, 2017 (edited) Bob Ross would be so proud! Example code: import java.awt.Color; import java.awt.Graphics2D; import java.util.List; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.model.NPC; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import com.liverare.api.PaintAPI; @ScriptManifest(author = "", info = "", logo = "", name = "Test", version = 0) public class Test extends Script { PaintAPI paint; Area safeSpace; List<NPC> guards; @Override public void onStart() throws InterruptedException { paint = new PaintAPI(); paint.exchangeContext(bot); safeSpace = myPlayer().getArea(5); } @Override public int onLoop() throws InterruptedException { guards = npcs.filter(Test::isGuard); return 100; } private static boolean isGuard(NPC npc) { return npc.getName().equals("Guard"); } @Override public void onPaint(Graphics2D g) { g.setColor(Color.BLACK); g.setBackground(Color.PINK); // dont worry bout checks fam, i do dat paint.drawMinimapArea(g, safeSpace); paint.drawEntities(g, guards, Test::guardToString, true, false, false, false, false, false, true); } private static String guardToString(NPC npc) { return "Health: " + npc.getHealthPercent() + ", xyz: " + npc.getPosition().toString(); } } Functions: public void drawLink(Graphics2D g, Entity entity1, Entity entity2) public void drawMinimapArea(Graphics2D g, org.osbot.rs07.api.map.Area area) public <T extends Position> void drawString(Graphics2D g, Function<T, String> toString, T position) public void drawString(Graphics2D g, String aString, Position position) public void drawString(Graphics2D g, String aString, Entity entity) public void drawEntity(Graphics2D g, Entity entity, String aString, boolean labelTile, boolean click, boolean cube, boolean minimap, boolean tile, boolean box, boolean wireframe) public void drawEntity(Graphics2D g, Entity entity, Function<T, String> getDescription, boolean labelTile, boolean click, boolean cube, boolean minimap, boolean tile, boolean box, boolean wireframe) public <T extends Entity> void drawEntities(Graphics2D g, Collection<T> entities, Function<T, String> getDescription, boolean labelTile, boolean click, boolean cube, boolean minimap, boolean tile, boolean tileCube, boolean wireframe) private void drawBox(Graphics2D g, Entity entity) private void drawBox(Graphics2D g, Position bottomTile, Position topTile) private void drawWireframe(Graphics2D g, Entity entity) private void drawClickBounds(Graphics2D g, Entity entity) private void drawCube(Graphics2D g, Entity entity) public void drawMinimapPoint(Graphics2D g, Vector3D v) public void drawMinimapLink(Graphics2D g, Vector3D a, Vector3D b) public void drawTile(Graphics2D g, Entity entity) public void drawTile(Graphics2D g, Position position) public static void drawPoint(Graphics2D g, Point point, int size) public static void drawPoint(Graphics2D g, int x, int y, int size) public static void drawShape(Graphics2D g, Shape shape) public static void drawString(Graphics2D g, String aString, int x, int y) public static void drawString(Graphics2D g, String aString, Point point) public static void drawString(Graphics2D g, String aString, Rectangle rectangle) Source: package com.liverare.api; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Area; import java.awt.geom.Rectangle2D; import java.util.Collection; import java.util.List; import java.util.function.Function; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.api.model.Entity; import org.osbot.rs07.api.model.Vector3D; import org.osbot.rs07.api.util.GraphicUtilities; import org.osbot.rs07.script.API; /** * * Painter utility * * @author LiveRare * */ public class PaintAPI extends API { /** * Initialise module */ @Override public void initializeModule() { } /** * Draw line between two in-game points * * @param g * - Graphic object * @param entity1 * - First entity point * @param entity2 * - Second entity point */ public void drawLink(Graphics2D g, Entity entity1, Entity entity2) { Area a1; Area a2; Rectangle2D r1; Rectangle2D r2; Point p1; Point p2; if (entity1 != null && entity2 != null) { a1 = GraphicUtilities.getModelArea(bot, entity1.getGridX(), entity1.getGridY(), entity1.getZ(), entity1.getModel()); a2 = GraphicUtilities.getModelArea(bot, entity2.getGridX(), entity2.getGridY(), entity2.getZ(), entity2.getModel()); r1 = a1.getBounds2D(); r2 = a2.getBounds(); p1 = new Point((int) r1.getCenterX(), (int) r1.getCenterY()); p2 = new Point((int) r2.getCenterX(), (int) r2.getCenterY()); if ((p1.x > 0 || p1.y > 0) && (p2.x > 0 || p2.y > 0)) { g.drawLine(p1.x, p1.y, p2.x, p2.y); } } } /** * Draw minimap area * * @param g * - Graphic object * @param area * - Area object */ public void drawMinimapArea(Graphics2D g, org.osbot.rs07.api.map.Area area) { Polygon areaPolygon; Polygon minimapPolygon; int minimapX; int minimapY; short[] minimapCoordinates; if (area != null) { areaPolygon = area.getPolygon(); if (areaPolygon != null) { minimapPolygon = new Polygon(); for (int i = 0; i < areaPolygon.npoints; i++) { minimapX = areaPolygon.xpoints[i]; minimapY = areaPolygon.ypoints[i]; minimapCoordinates = GraphicUtilities.getMinimapScreenCoordinate(bot, minimapX, minimapY); if (minimapCoordinates != null) { minimapX = (int) minimapCoordinates[0]; minimapY = (int) minimapCoordinates[1]; minimapPolygon.addPoint(minimapX, minimapY); } } drawShape(g, minimapPolygon); } } } /** * Draw a dynamically generated, position-related string and set its location to * an in-game position * * @param g * - Graphic object * @param toString * - string function * @param position * - Position object */ public <T extends Position> void drawString(Graphics2D g, Function<T, String> toString, T position) { if (toString != null && position != null) { drawString(g, toString.apply(position), position); } } /** * Draw string for a tile * * @param g * - Graphic object * @param aString * - String object * @param position * - Position object * @see {@link PaintAPI#drawString(Graphics2D, String, Rectangle)} */ public void drawString(Graphics2D g, String aString, Position position) { Rectangle2D rectangle; Polygon polygon; if (position != null && position.isVisible(bot)) { polygon = position.getPolygon(bot); if (polygon != null) { rectangle = polygon.getBounds2D(); drawString(g, aString, rectangle.getBounds()); } } } /** * Draw string for an entity * * @param g * - Graphic object * @param aString * - String object * @param entity * - Entity object */ public void drawString(Graphics2D g, String aString, Entity entity) { Rectangle rectangle; if (entity != null && entity.isVisible()) { rectangle = GraphicUtilities.getModelBoundingBox(bot, entity.getGridX(), entity.getGridY(), entity.getZ(), entity.getModel()); if (rectangle != null) { drawString(g, aString, rectangle); } } } /** * Draw entity * * @param g * - Graphic object * @param entity * - Entity object * @param aString * - String object * @param labelTile * - <tt>Label relative to tile</tt> * @param click * - <tt>Draw click box</tt> * @param cube * - <tt>Draw model cube</tt> * @param minimap * - <tt>Draw minimap point</tt> * @param tile * - <tt>Draw tile</tt> * @param box * - <tt>Draw 3D wire-frame box spanning from bottom to top tile</tt> * @param wireframe * - <tt>Draw wire-frame</tt> * @see {@link PaintAPI#drawClickBounds(Graphics2D, Entity)} * @see {@link PaintAPI#drawCube(Graphics2D, Entity)} * @see {@link PaintAPI#drawMinimapPoint(Graphics2D, Vector3D)} * @see {@link PaintAPI#drawTile(Graphics2D, Entity)} * @see {@link PaintAPI#drawBox(Graphics2D, Entity)} * @see {@link PaintAPI#drawWireframe(Graphics2D, Entity)} * @see {@link PaintAPI#drawString(Graphics2D, String, Position)} * @see {@link PaintAPI#drawString(Graphics2D, String, Entity)} */ public void drawEntity(Graphics2D g, Entity entity, String aString, boolean labelTile, boolean click, boolean cube, boolean minimap, boolean tile, boolean box, boolean wireframe) { if (entity != null) { if (minimap) { drawMinimapPoint(g, entity); } if (entity.isVisible()) { if (click) { drawClickBounds(g, entity); } if (cube) { drawCube(g, entity); } if (tile) { drawTile(g, entity); } if (box) { drawBox(g, entity); } if (wireframe) { drawWireframe(g, entity); } if (labelTile) { drawString(g, aString, new Position(entity.getX(), entity.getY(), entity.getZ() + 1)); } else { drawString(g, aString, entity); } } } } /** * Draw entity * * @param g * - Graphic object * @param entity * - Entity object * @param Function<Entity, * String> - get description * @param labelTile * - <tt>Label relative to tile</tt> * @param click * - <tt>Draw click box</tt> * @param cube * - <tt>Draw model cube</tt> * @param minimap * - <tt>Draw minimap point</tt> * @param tile * - <tt>Draw tile</tt> * @param tileCube * - <tt>Draw tile cube</tt> * @param wireframe * - <tt>Draw wireframe</tt> * @see {@link PaintAPI#drawEntity(Graphics2D, Entity, String, boolean, boolean, boolean, boolean, boolean, boolean, boolean)} */ public <T extends Entity> void drawEntity(Graphics2D g, T entity, Function<T, String> getDescription, boolean labelTile, boolean click, boolean cube, boolean minimap, boolean tile, boolean tileCube, boolean wireframe) { String aString = null; if (getDescription != null && entity != null) { aString = getDescription.apply(entity); } drawEntity(g, entity, aString, labelTile, click, cube, minimap, tile, tileCube, wireframe); } /** * Draw entities * * @param g * - Graphic object * @param entity * - Entity object * @param Function<Entity, * String> - get description * @param labelTile * - <tt>Label relative to tile</tt> * @param click * - <tt>Draw click box</tt> * @param cube * - <tt>Draw model cube</tt> * @param minimap * - <tt>Draw minimap point</tt> * @param tile * - <tt>Draw tile</tt> * @param tileCube * - <tt>Draw tile cube</tt> * @param wireframe * - <tt>Draw wireframe</tt> * @see {@link PaintAPI#drawEntity(Graphics2D, Entity , String , boolean , boolean , boolean , boolean , boolean , boolean , boolean )} */ public <T extends Entity> void drawEntities(Graphics2D g, Collection<T> entities, Function<T, String> getDescription, boolean labelTile, boolean click, boolean cube, boolean minimap, boolean tile, boolean tileCube, boolean wireframe) { if (entities != null && !entities.isEmpty()) { entities.forEach(entity -> { if (entity != null) { String aString = null; if (getDescription != null) { aString = getDescription.apply(entity); } drawEntity(g, entity, aString, labelTile, click, cube, minimap, tile, tileCube, wireframe); } }); } } /** * Draw box * * @param g * - Graphic object * @param entity * - Entity object * @see {@link PaintAPI#drawBox(Graphics2D, Position)} */ private void drawBox(Graphics2D g, Entity entity) { Position bottomTile; Position topTile; if (entity != null) { bottomTile = entity.getPosition(); topTile = new Position(bottomTile.getX(), bottomTile.getY(), bottomTile.getZ() + 1); drawBox(g, bottomTile, topTile); } } /** * Draw box * * @param g * - Graphic object * @param position * - Position object A * @param position * - Position object B * @see {@link PaintAPI#drawShape(Graphics2D, Shape)} */ private void drawBox(Graphics2D g, Position bottomTile, Position topTile) { Polygon bottom; Polygon top; Polygon side1; Polygon side2; Polygon side3; Polygon side4; if (bottomTile != null) { bottom = bottomTile.getPolygon(bot); top = topTile.getPolygon(bot); side1 = new Polygon( new int[] { top.xpoints[0], top.xpoints[1], bottom.xpoints[1], bottom.xpoints[0] }, new int[] { top.ypoints[0], top.ypoints[1], bottom.ypoints[1], bottom.ypoints[0] }, 4); side2 = new Polygon( new int[] { top.xpoints[1], top.xpoints[2], bottom.xpoints[2], bottom.xpoints[1] }, new int[] { top.ypoints[1], top.ypoints[2], bottom.ypoints[2], bottom.ypoints[1] }, 4); side3 = new Polygon( new int[] { top.xpoints[2], top.xpoints[3], bottom.xpoints[3], bottom.xpoints[2] }, new int[] { top.ypoints[2], top.ypoints[3], bottom.ypoints[3], bottom.ypoints[2] }, 4); side4 = new Polygon( new int[] { top.xpoints[3], top.xpoints[0], bottom.xpoints[0], bottom.xpoints[3] }, new int[] { top.ypoints[3], top.ypoints[0], bottom.ypoints[0], bottom.ypoints[3] }, 4); drawShape(g, bottom); drawShape(g, side1); drawShape(g, side2); drawShape(g, side3); drawShape(g, side4); drawShape(g, top); } } /** * Draw wireframe * * @param g * - Graphic object * @param entity * - Entity object * @see {@link PaintAPI#drawShape(Graphics2D, Shape)} */ private void drawWireframe(Graphics2D g, Entity entity) { List<Polygon> polygons = GraphicUtilities.getModelMeshTriangles(bot, entity.getGridX(), entity.getGridY(), entity.getZ(), entity.getModel()); if (polygons != null && !polygons.isEmpty()) { for (Polygon polygon : polygons) { drawShape(g, polygon); } } } /** * Draw click bounds * * @param g * - Graphic object * @param entity * - Entity object */ private void drawClickBounds(Graphics2D g, Entity entity) { Rectangle rectangle = GraphicUtilities.getModelBoundingBox(bot, entity.getGridX(), entity.getGridY(), entity.getZ(), entity.getModel()); if (rectangle != null) { drawShape(g, rectangle); } } /** * Draw box around entity * * @param g * - Graphic object * @param entity * - Entity object */ private void drawCube(Graphics2D g, Entity entity) { Area area = GraphicUtilities.getCubicArea(bot, entity.getGridX(), entity.getGridY(), entity.getZ(), entity.getSizeX(), entity.getSizeY(), entity.getHeight()); if (area != null) { drawShape(g, area); } } /** * Draw minimap point * * @param g * - Graphic object * @param v * - 3D Vector */ public void drawMinimapPoint(Graphics2D g, Vector3D v) { short[] minimapPosition = null; int x = 0; int y = 0; if (v != null) { minimapPosition = GraphicUtilities.getMinimapScreenCoordinate(bot, v.getX(), v.getY()); if (minimapPosition != null) { x = (int) minimapPosition[0]; y = (int) minimapPosition[1]; drawPoint(g, x, y, 3); } } } /** * Draw links between vectors * * @param g * - Graphic object * @param a * - 3D Vector A * @param b * - 3D Vector B */ public void drawMinimapLink(Graphics2D g, Vector3D a, Vector3D b) { short[] minimapPositionA; short[] minimapPositionB; int x1; int y1; int x2; int y2; if (a != null && b != null) { minimapPositionA = GraphicUtilities.getMinimapScreenCoordinate(bot, a.getX(), a.getY()); minimapPositionB = GraphicUtilities.getMinimapScreenCoordinate(bot, b.getX(), b.getY()); if (minimapPositionA != null && minimapPositionB != null) { x1 = minimapPositionA[0]; y1 = minimapPositionA[1]; x2 = minimapPositionB[0]; y2 = minimapPositionB[1]; if (x1 != x2 && y1 != y2 && (x1 > 0 || y1 > 0) && (x2 > 0 || y2 > 0)) { g.drawLine(x1, y1, x2, y2); } } } } /** * Draw tile * * @param g * - Graphic object * @param entity * - entity object * @see {@link PaintAPI#drawTile(Graphics2D, Position)} */ public void drawTile(Graphics2D g, Entity entity) { if (entity != null) { drawTile(g, entity.getPosition()); } } /** * Draw tile * * @param g * - Graphic object * @param position * - Position object */ public void drawTile(Graphics2D g, Position position) { Polygon polygon = null; if (position != null && position.isVisible(bot)) { polygon = position.getPolygon(bot); drawShape(g, polygon); } } /** * Draw point * * @param g * - Graphic object * @param point * - Point object * @param size * - Size of the oval */ public static void drawPoint(Graphics2D g, Point point, int size) { if (point != null) { drawPoint(g, point.x, point.y, size); } } /** * Draw point * * @param g * - Graphic object * @param x * - X coordinate * @param y * - Y coordinate * @param size * - Size of the oval */ public static void drawPoint(Graphics2D g, int x, int y, int size) { final Color bg = g.getBackground(); final Color fg = g.getColor(); g.setColor(bg); g.fillOval(x - size, y - size, size * 2, size * 2); g.setColor(fg); g.drawOval(x - size, y - size, size * 2, size * 2); } /** * Draw and fill shape * * @param g * - Graphic object * @param shape * - Shape object */ public static void drawShape(Graphics2D g, Shape shape) { final Color bg = g.getBackground(); final Color fg = g.getColor(); if (shape != null) { if (bg != null) { g.setColor(bg); g.fill(shape); g.setColor(fg); } g.draw(shape); } } /** * Draw string * * @param g * - Graphic object * @param aString * - String object * @param x * - X coordinate * @param y * - Y coordinate */ public static void drawString(Graphics2D g, String aString, int x, int y) { final Color bg = g.getBackground(); final Color fg = g.getColor(); if (aString != null && !aString.isEmpty()) { if (bg != null) { g.setColor(bg); g.drawString(aString, x + 1, y + 1); g.drawString(aString, x + 1, y - 1); g.drawString(aString, x - 1, y + 1); g.drawString(aString, x - 1, y - 1); g.setColor(fg); } g.drawString(aString, x, y); } } /** * Draw string * * @param g * - Graphic object * @param aString * - String object * @param point * - Point object * @see {@link PaintAPI#drawString(Graphics2D, String, int, int)} */ public static void drawString(Graphics2D g, String aString, Point point) { if (point != null) { drawString(g, aString, point.x, point.y); } } /** * Draw centred string above rectangle * * @param g * - Graphic object * @param aString * - String object * @param rectangle * - Rectangle object */ public static void drawString(Graphics2D g, String aString, Rectangle rectangle) { final FontMetrics fontMetrics = g.getFontMetrics(); double x = 0D; double y = 0D; int stringWidth = 0; if (aString != null && !aString.isEmpty() && rectangle != null) { stringWidth = fontMetrics.stringWidth(aString); x += rectangle.getCenterX(); x -= (stringWidth / 2); y = rectangle.getY(); drawString(g, aString, (int) x, (int) y); } } } Edited October 3, 2017 by liverare pesky little function apparently didn't want commenting :( 11 Quote Link to comment Share on other sites More sharing options...
Chris Posted September 23, 2017 Share Posted September 23, 2017 love you babe Quote Link to comment Share on other sites More sharing options...
ThatGamerBlue Posted September 23, 2017 Share Posted September 23, 2017 i fucking love you 1 Quote Link to comment Share on other sites More sharing options...
Juggles Posted September 23, 2017 Share Posted September 23, 2017 Interesting..... zzzzzz 1 Quote Link to comment Share on other sites More sharing options...
TheWind Posted September 23, 2017 Share Posted September 23, 2017 My question is why did @Alek depreciate the method exchangeContext(Bot bot)? Quote Link to comment Share on other sites More sharing options...
liverare Posted September 24, 2017 Author Share Posted September 24, 2017 8 hours ago, TheWind said: My question is why did @Alek depreciate the method exchangeContext(Bot bot)? Deprecated for internal use only. Building APIs is more of a developer's job than it is a scripters, so it's likely deprecated just to ward of those who don't know what they're doing. Quote Link to comment Share on other sites More sharing options...
TheWind Posted September 26, 2017 Share Posted September 26, 2017 On 9/24/2017 at 4:54 AM, liverare said: Deprecated for internal use only. Building APIs is more of a developer's job than it is a scripters, so it's likely deprecated just to ward of those who don't know what they're doing. I guess that means me :(, but I really do want to learn. I have a few questions: 1) Why did you extend the class API instead of MethodProvider and not use the initializeModule() method? 2) Why even call the method exchangeContext(getBot()) when the class you made would work without it? I guess I'm not really understanding what it does unless it's doing something behind the scenes which may be harder to understand unless you know how the bot itself works... Quote Link to comment Share on other sites More sharing options...
liverare Posted September 26, 2017 Author Share Posted September 26, 2017 (edited) 6 hours ago, TheWind said: I guess that means me :(, but I really do want to learn. I have a few questions: 1) Why did you extend the class API instead of MethodProvider and not use the initializeModule() method? 2) Why even call the method exchangeContext(getBot()) when the class you made would work without it? I guess I'm not really understanding what it does unless it's doing something behind the scenes which may be harder to understand unless you know how the bot itself works... Semantics. I wrote and released an API, not a MethodProvider. The initializeModule function doesn't need to be used, but I've used it in my other APIs. For instance, in my hunting API, I use it to reset values and variables, but also to find some other entities, so that I can completely reset the hunt each time I finish one. exchangeContext is required to be called, so the MethodProvider can capture an instance of your bot and work in relation to it. If you look at the methods I listed and look for the ones that don't contain "static" in their deceleration, that's because, for one reason or another, it depends on having access to the bot instance. If I only had static variables then I wouldn't need to pass in the bot instance, but I'd still call it, if only because I've got OCD and instantiating a new API and not giving it the bot context would trigger me. Edited September 26, 2017 by liverare 1 Quote Link to comment Share on other sites More sharing options...
TheWind Posted September 26, 2017 Share Posted September 26, 2017 42 minutes ago, liverare said: Semantics. I wrote and released an API, not a MethodProvider. The initializeModule function doesn't need to be used, but I've used it in my other APIs. For instance, in my hunting API, I use it to reset values and variables, but also to find some other entities, so that I can completely reset the hunt each time I finish one. exchangeContext is required to be called, so the MethodProvider can capture an instance of your bot and work in relation to it. If you look at the methods I listed and look for the ones that don't contain "static" in their deceleration, that's because, for one reason or another, it depends on having access to the bot instance. If I only had static variables then I wouldn't need to pass in the bot instance, but I'd still call it, if only because I've got OCD and instantiating a new API and not giving it the bot context would trigger me. Thank you for answering with such detail. As for your answer to the second question, it really raises more questions as opposed to satisfying my curiosity, but I'll leave it with just those two questions for now. 1 Quote Link to comment Share on other sites More sharing options...
whipz Posted September 26, 2017 Share Posted September 26, 2017 Love the paint API, looks awesome just a question, how do you make background transparent ? everything I have tried either turns it white or black Quote Link to comment Share on other sites More sharing options...
liverare Posted September 26, 2017 Author Share Posted September 26, 2017 17 minutes ago, whipz said: Love the paint API, looks awesome just a question, how do you make background transparent ? everything I have tried either turns it white or black g.setBackground(null) Quote Link to comment Share on other sites More sharing options...
whipz Posted September 26, 2017 Share Posted September 26, 2017 25 minutes ago, liverare said: g.setBackground(null) legend thanks mate, will edit when i have tested, going to bed (will also post credits when/if i release a script with your paint) which im sure I will eventually, as it's so useful Quote Link to comment Share on other sites More sharing options...
Alek Posted September 28, 2017 Share Posted September 28, 2017 On 9/23/2017 at 7:59 PM, TheWind said: My question is why did @Alek depreciate the method exchangeContext(Bot bot)? I'm flattered that you think I wrote OSBot 2 form scratch. Quote Link to comment Share on other sites More sharing options...
Prozen Posted September 28, 2017 Share Posted September 28, 2017 Definitely going to use this, thanks. 1 Quote Link to comment Share on other sites More sharing options...
liverare Posted September 28, 2017 Author Share Posted September 28, 2017 (edited) I've made a minor change to the drawEntity function, because it would only render the entity on the minimap if it was also visible. Now it'll render it so long as it's on the minimap. There's one thing I dislike and that's when something will render, but it'll be stretched to the top-left of the screen because it's partially visible, like a partially visible tile. That's down to some core OSBot functions. I'll have to add in some checks to avoid rendering those later. Edited September 28, 2017 by liverare Quote Link to comment Share on other sites More sharing options...