meganide97 Posted July 5, 2018 Share Posted July 5, 2018 (edited) Hey just wrote my first ever OSbot script after having studied Java for 2 days with no prior experience whatsoever, just wanted to ask for some feedback. It's a very basic mining script that mines Copper ore and then banks, so far it seems to work. Spoiler package core; import java.awt.Graphics2D; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.constants.Banks; import org.osbot.rs07.api.model.RS2Object; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.ConditionalSleep; @ScriptManifest(author = "You", info = "My first script", name = "Miner", version = 0, logo = "") public class Miner extends Script { @Override public void onStart() { log("Let's get started!"); } @Override public int onLoop() throws InterruptedException { RS2Object ore = getObjects().closest(7453); Area alkharidmine = new Area(3295, 3308, 3303, 3314); if (alkharidmine.contains(myPosition())) { if (!ore.isVisible()){ getCamera().toEntity(ore); } if (ore != null && !inventory.isFull() && !myPlayer().isAnimating()) { log("mining rock"); ore.interact("Mine"); new ConditionalSleep(500, 750) { @Override public boolean condition() throws InterruptedException { log("sleeping"); return myPlayer().isAnimating(); } }.sleep(); if (random(0, 50) >= 43) { log("random camera movement"); getCamera().moveYaw(random(0, 360)); getCamera().movePitch(random(42, 67)); } } else if (inventory.isFull()) { log("Inventory is full and we are walking to bank"); getWalking().webWalk(Banks.AL_KHARID); if (Banks.AL_KHARID.contains(myPosition()) && !getBank().open() && inventory.isFull()) { log("we are in bank and inv is full, opening bank"); getBank().open(); new ConditionalSleep(500, 2000) { @Override public boolean condition() throws InterruptedException { return getBank().isOpen(); } }.sleep(); }else{ log("Depositing Ore and walking back to mine"); getBank().deposit("Copper ore", 28); getWalking().webWalk(alkharidmine); } } } else { log("Not in Al-Kharid mine, Walking there"); getWalking().webWalk(alkharidmine); } return random(200, 300); } @Override public void onExit () { log("Thanks for running my Miner"); } @Override public void onPaint (Graphics2D g){ } } What I want to add next is a GUI that lets the user input what kind of ore & location they want to mine in and bank, and also add paint. However I have no idea whatsoever how to this so I will have to study more before doing this. I also read about dividing the script in multiple classes and using the switch command to make it look cleaner so that I wouldn't have to use so many if statements. Will update you guys on the script as I add new stuff. Edit 1: - Cleaned up the code a little bit after reading the feedback. - Added paint (Total runtime, xp gained, lvls gained, total gp made, gp/hour, ore mined, xp/hr. - Added some antiban (it now randomly hovers the mining skillicon). - Changed it to mine iron ore instead. Picture of the bot running: https://i.gyazo.com/87b8d4cf40e87cb4f054b9825d4eae38.png Updated code: Spoiler package core; import java.awt.Graphics2D; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.constants.Banks; import org.osbot.rs07.api.model.RS2Object; import org.osbot.rs07.api.ui.RS2Widget; import org.osbot.rs07.api.ui.Skill; import org.osbot.rs07.input.mouse.RectangleDestination; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.ConditionalSleep; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.text.DecimalFormat; import java.text.DecimalFormat; import java.util.concurrent.TimeUnit; @ScriptManifest(author = "You", info = "My first script", name = "Miner", version = 0, logo = "") public final class Miner extends Script { //variables for XP per hour private int xpPerHour; private int totalXpPerHour; //Variables for GP made per hour private int gpPerHour; private int totalGpPerHour; //Variables for TOTAL GP MADE private int CostofItem; private int ItemsMade; private double gpGained; private double totalGpGained; //Variables for levels gained private int beginningLVL; private int currentLVL; private int LVLSgained; // Variables for Xp gained private int beginningXP; private int currentXp; private int xpGained; //Paint variable declarations private long timeBegan; private long timeRan; @Override public final void onStart(){ timeBegan = System.currentTimeMillis(); beginningXP = skills.getExperience(Skill.MINING); beginningLVL = skills.getStatic(Skill.MINING); CostofItem = 169; } @Override public int onLoop() throws InterruptedException { RS2Object ore = getObjects().closest(new Area(3294, 3311, 3296, 3308), 7455, 7488); Area alkharidmine = new Area(3295, 3308, 3303, 3314); RS2Widget skillicon = getWidgets().get(548,49); RS2Widget miningicon = getWidgets().get(320,17); RS2Widget inventoryicon = getWidgets().get(548, 58); if (ore != null && !inventory.isFull() && !myPlayer().isAnimating() && alkharidmine.contains(myPosition())) { log("mining rock"); ore.interact("Mine"); new ConditionalSleep(3000, 300) { @Override public boolean condition() throws InterruptedException { log("sleeping"); return myPlayer().isAnimating() || !ore.exists(); //we will stop sleeping before the timeout if // player is animating or if the ore is not longer there (someone mined it) } }.sleep(); //start sleeping ItemsMade += 1; if (random(0, 50) >= 46) { log("random camera movement"); getCamera().moveYaw(random(0, 360)); getCamera().movePitch(random(42, 67)); } if (random(0, 100) >=95 && skillicon != null && miningicon != null && inventoryicon != null){ log("Clicking skillicon"); skillicon.interact(); miningicon.hover(); new ConditionalSleep(2000, 1000) { @Override public boolean condition() throws InterruptedException { return !myPlayer().isAnimating(); } }.sleep(); inventoryicon.interact(); new ConditionalSleep(2000, 1000) { @Override public boolean condition() throws InterruptedException { return !myPlayer().isAnimating(); } }.sleep(); } } else if (inventory.isFull()) { log("Inventory is full and we are walking to bank"); getWalking().webWalk(Banks.AL_KHARID); if (Banks.AL_KHARID.contains(myPosition()) && !getBank().open()) { log("we are in bank and inv is full, opening bank"); new ConditionalSleep(3000, 500) { @Override public boolean condition() throws InterruptedException { return getBank().isOpen(); //we will stop sleeping when bank is open. } }.sleep(); } else { log("Depositing Ore and walking back to mine"); getBank().depositAll(); getWalking().webWalk(alkharidmine); } } else if (!alkharidmine.contains(myPosition())) { log("Not in Al-Kharid mine, Walking there"); getWalking().webWalk(alkharidmine); } return random(200, 300); } @Override public void onExit () { log("Thanks for running my Miner"); } @Override public void onPaint (Graphics2D g){ timeRan = System.currentTimeMillis() - this.timeBegan; g.drawString("Time ran: " + ft(timeRan), 13, 245); g.drawString("XP Gained: " + xpGained, 13, 260); g.drawString("LVLS Gained: " + LVLSgained, 13, 275); currentXp = skills.getExperience(Skill.MINING); xpGained = currentXp - beginningXP; currentLVL = skills.getStatic(Skill.MINING); LVLSgained = currentLVL - beginningLVL; gpGained = ItemsMade * CostofItem; totalGpGained = gpGained / 1000; DecimalFormat df = new DecimalFormat("#.#"); //rounds to 1 decimal g.drawString("Total gp made: " +df.format(totalGpGained) + " k", 13, 290); g.drawString("Ore mined: " + ItemsMade, 13,320); gpPerHour = (int)(gpGained / ((System.currentTimeMillis() - timeBegan) / 3600000.0D)); totalGpPerHour = gpPerHour / 1000; g.drawString("GP/hour: " + df.format(totalGpPerHour) + " k/hr", 13, 305); xpPerHour = (int)(xpGained / ((System.currentTimeMillis() - timeBegan) / 3600000.0D)); totalXpPerHour = xpPerHour / 1000; g.drawString("XP/hour: " + df.format(xpPerHour) + " XP/hr", 13, 335); } //Time ran formatting to Days:Hours:Seconds private String ft(long duration) { String res = ""; long days = TimeUnit.MILLISECONDS.toDays(duration); long hours = TimeUnit.MILLISECONDS.toHours(duration) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration)); long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS .toHours(duration)); long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS .toMinutes(duration)); if (days == 0) { res = (hours + ":" + minutes + ":" + seconds); } else { res = (days + ":" + hours + ":" + minutes + ":" + seconds); } return res; } } Future updates: - Will add a GUI that will let you choose whether you want to powermine or bank, and also lets you choose which ore to mine that supports more locations and not just the Al-Kharid mine. - Will have to implement some kind of method that gets the GE prices for different ores to calculate the gp/hour. - For the powermining part, I want it to use shift-click to drop if possible. Appreciate further feedback, thanks! Edit 2: - Script now remembers starting position so you can start it from any mine and it will automatically walk to the closest bank. - Filtered deposit item to bank everything that ends with ore so skillers can have pickaxe in inventory. Edit 3: - Added a GUI that lets you choose which ores you want to mine (based on color). - Cleaned up the code a little bit. Thanks @Vilius for the help! Edit 4: - Added a powermining checkbox in GUI that supports shift dropping. - Script is now finished!!! :-) Code: Spoiler package miner; package miner; import java.awt.Graphics2D; import org.osbot.rs07.api.Bank; import org.osbot.rs07.api.Objects; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.api.map.constants.Banks; import org.osbot.rs07.api.model.Entity; import org.osbot.rs07.api.model.Item; import org.osbot.rs07.api.model.RS2Object; import org.osbot.rs07.api.ui.RS2Widget; import org.osbot.rs07.api.ui.Skill; import org.osbot.rs07.api.ui.Tab; import org.osbot.rs07.input.mouse.RectangleDestination; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.ConditionalSleep; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.text.DecimalFormat; import java.text.DecimalFormat; import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @ScriptManifest(author = "Meganide97", info = "Will mine anything anywhere", name = "AIO Miner", version = 0, logo = "http://jambonium.co.uk/wp-content/uploads/2015/10/mining_icon.png") public final class main extends Script { public boolean powerMine = false; //preventing script from running when GUI is open Object lock = new Object(); //telling that gui exists private gui gui = new gui(); //String variable that changes ore id depending on the user input in the GUI. public Rock ore = Rock.CLAY; //variable banks private final Area[] BANKS = { Banks.AL_KHARID, Banks.ARDOUGNE_NORTH, Banks.ARDOUGNE_NORTH, Banks.ARDOUGNE_SOUTH, Banks.CAMELOT, Banks.CANIFIS, Banks.CASTLE_WARS, Banks.CATHERBY, Banks.DRAYNOR, Banks.DUEL_ARENA, Banks.EDGEVILLE, Banks.FALADOR_EAST, Banks.FALADOR_WEST, Banks.GRAND_EXCHANGE, Banks.GNOME_STRONGHOLD, Banks.LUMBRIDGE_UPPER, Banks.VARROCK_EAST, Banks.VARROCK_WEST, Banks.YANILLE }; //walk to closest bank method public void walkToClosestBank(){ getWalking().webWalk(BANKS); } //saving startposition private Position startPos; //start script in right position private Area startArea; //Paint variable declarations private long timeBegan; private long timeRan; @Override public final void onStart() throws InterruptedException{ gui.run(this); //running gui on start synchronized(lock){ lock.wait(); } log("Starting script"); timeBegan = System.currentTimeMillis(); getExperienceTracker().start(Skill.MINING); startPos = myPlayer().getPosition(); startArea = myPlayer().getArea(1); log("Your starting position is: " + startPos); } @Override public int onLoop() throws InterruptedException { RS2Widget miningicon = getWidgets().get(320, 17); if (ore != null && !inventory.isFull() && !myPlayer().isAnimating()) { ore.getClosestWithOre(getObjects()).ifPresent(rock -> { if (startArea.contains(rock)) rock.interact("Mine"); }); log("mining " + ore); new ConditionalSleep(1000, 300) { @Override public boolean condition() throws InterruptedException { log("sleeping"); return myPlayer().isAnimating() || getDialogues().isPendingContinuation(); //we will stop sleeping before the timeout if // player is animating or if the ore is not longer there (someone mined it) } }.sleep(); //start sleeping if (random(0, 50) > 49) { log("random camera movement"); getCamera().moveYaw(random(0, 360)); getCamera().movePitch(random(42, 67)); } if (random(0, 100) > 99 && miningicon != null) { // if (!getTabs().getOpen().equals(Tab.SKILLS)) { if (getTabs().open(Tab.SKILLS)) { log("Clicking skillicon"); miningicon.hover(); sleep(3500); getTabs().open(Tab.INVENTORY); new ConditionalSleep(2000, 1000) { @Override public boolean condition() throws InterruptedException { return myPlayer().isAnimating(); } }.sleep(); } } } else if (inventory.isFull() && powerMine == false) { log("Inventory is full and we are walking to bank"); walkToClosestBank(); if (!getBank().open()) { log("we are in bank and inv is full, opening bank"); new ConditionalSleep(3000, 500) { @Override public boolean condition() throws InterruptedException { return getBank().isOpen(); //we will stop sleeping when bank is open. } }.sleep(); } else { log("Depositing Ore and walking back to startposition"); getBank().depositAll(i -> i.getName().endsWith("ore")); getBank().depositAll("Clay"); getBank().depositAll("Coal"); getWalking().webWalk(startPos); } } else if ( powerMine == true && inventory.isFull() && !getInventory().isItemSelected() && getTabs().open(Tab.INVENTORY)) { log("Dropping " + ore ); if ( getInventory().dropAll(n -> n.getName().endsWith("ore")) ); if ( getInventory().dropAll("Clay") ); if ( getInventory().dropAll("Coal") ); } else if (getInventory().isItemSelected()) { log("deselecting " + ore ); getInventory().deselectItem(); } return random(200, 300); } @Override public void onExit () { log("Thanks for running my AIO Miner"); } @Override public void onPaint (Graphics2D g){ timeRan = System.currentTimeMillis() - this.timeBegan; g.drawString("Time ran: " + ft(timeRan), 13, 275); g.drawString("XP Gained: " + getExperienceTracker().getGainedXP(Skill.MINING), 13, 290); g.drawString("XP/hour: " + getExperienceTracker().getGainedXPPerHour(Skill.MINING) + " XP/hr", 13, 305); g.drawString("LVLS Gained: " + getExperienceTracker().getGainedLevels(Skill.MINING), 13, 320); g.drawString("Time to Lvl: " + ft(getExperienceTracker().getTimeToLevel(Skill.MINING)), 13 , 335); } //Time ran formatting to Days:Hours:Seconds private String ft ( long duration) { String res = ""; long days = TimeUnit.MILLISECONDS.toDays(duration); long hours = TimeUnit.MILLISECONDS.toHours(duration) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration)); long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS .toHours(duration)); long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS .toMinutes(duration)); if (days == 0) { res = (hours + ":" + minutes + ":" + seconds); } else { res = (days + ":" + hours + ":" + minutes + ":" + seconds); } return res; } } Edited July 10, 2018 by meganide97 Added update. 2 Quote Link to comment Share on other sites More sharing options...
D Bolter Posted July 5, 2018 Share Posted July 5, 2018 Congrats on your first script man. May I ask what guides on osbot helped you learn about the API? Quote Link to comment Share on other sites More sharing options...
Chris Posted July 5, 2018 Share Posted July 5, 2018 Logic needs to be relooked at and worked on possible nullpointer before you even check if ore is null banking is poor logic and can be rewritten. You can see an example here: https://github.com/christophernarciso/programming/blob/master/Meire %26 Brito Automation [OSBot.org]/OSBot Scripting Open Source Projects/Scripts/CAccountEvaluator/src/Evaluator.java#L108 Quote Link to comment Share on other sites More sharing options...
dogetrix Posted July 5, 2018 Share Posted July 5, 2018 Not bad for 2 days of study. Here are some specifics: you can get rid of the second call to getBank().open(), because you already called it once in the if statement, it is redundant get rid of the inventory.isFull() in the same if statement as above, because you already checked it once, so checking it a second time is redundant the conditionalSleeps that you are using can be broken, the timeout is longer than the sleep delay check (the constructor is ConditionalSleep(int timeout, int sleepTime)) the indentation at the end is confusing, you should probably clean that up (banking has a lot of issues in general) you called ore.isVisible() before nullchecking ore, so it could throw a null pointer exception probably some more that I missed Quote Link to comment Share on other sites More sharing options...
CJ7 Posted July 5, 2018 Share Posted July 5, 2018 Also, I believe this piece of code: if (!ore.isVisible()){ getCamera().toEntity(ore); } aside from the possibility of causing nullpointer exceptions is also unnecassesary, since you're calling "ore.interact" after that. Interact also moves the camera! Quote Link to comment Share on other sites More sharing options...
meganide97 Posted July 5, 2018 Author Share Posted July 5, 2018 (edited) 9 hours ago, D Bolter said: Congrats on your first script man. May I ask what guides on osbot helped you learn about the API? Thanks man! I watched some youtube videos and read tutorials here on the forums as well as read snippets of scripts to get an idea how to type the code. Chris has a discord as well where he teaches you the basics of coding. Here are some links that were very helpful to me: there is a link to the discord ^ up there. Also I've just started watching these youtube guides which are very helpful: Gl man Edited July 5, 2018 by meganide97 1 Quote Link to comment Share on other sites More sharing options...
meganide97 Posted July 5, 2018 Author Share Posted July 5, 2018 1 hour ago, CJ7 said: Also, I believe this piece of code: if (!ore.isVisible()){ getCamera().toEntity(ore); } aside from the possibility of causing nullpointer exceptions is also unnecassesary, since you're calling "ore.interact" after that. Interact also moves the camera! Thanks! Removed that line from the code, also as Chris pointed out I did this command before even nullchecking which was a mistake Quote Link to comment Share on other sites More sharing options...
meganide97 Posted July 5, 2018 Author Share Posted July 5, 2018 (edited) 6 hours ago, dogetrix said: Not bad for 2 days of study. Here are some specifics: you can get rid of the second call to getBank().open(), because you already called it once in the if statement, it is redundant get rid of the inventory.isFull() in the same if statement as above, because you already checked it once, so checking it a second time is redundant the conditionalSleeps that you are using can be broken, the timeout is longer than the sleep delay check (the constructor is ConditionalSleep(int timeout, int sleepTime)) the indentation at the end is confusing, you should probably clean that up (banking has a lot of issues in general) you called ore.isVisible() before nullchecking ore, so it could throw a null pointer exception probably some more that I missed Thanks for the feedback! Cleaned the code up a little, but what I don't understand is why I should get rid of the call to getBank().open(), if I remove this line it won't open up the bank. Edit: Just tried what you said and it opened up the bank anyway, does the deposit function also open the bank? I'm kinda confused here as to what command decided to open the bank. Edited July 5, 2018 by meganide97 Quote Link to comment Share on other sites More sharing options...
Explv Posted July 5, 2018 Share Posted July 5, 2018 (edited) @meganide97 what's this? @Muffins @Chris @Night @Mio Edited July 5, 2018 by Explv 5 2 Quote Link to comment Share on other sites More sharing options...
meganide97 Posted July 5, 2018 Author Share Posted July 5, 2018 17 minutes ago, Explv said: @meganide97 what's this? @Muffins @Chris @Night @Mio Old accounts I created before, I tried running several clients at once but didn't work and I didn't know it was against the rules to have several accounts, however this is the only account I use now that I'm better informed. You can go ahead and remove those accounts, thanks. 9 hours ago, Chris said: Logic needs to be relooked at and worked on possible nullpointer before you even check if ore is null banking is poor logic and can be rewritten. You can see an example here: https://github.com/christophernarciso/programming/blob/master/Meire %26 Brito Automation [OSBot.org]/OSBot Scripting Open Source Projects/Scripts/CAccountEvaluator/src/Evaluator.java#L108 Thanks for the feedback, have cleaned up the code a little will update soon Quote Link to comment Share on other sites More sharing options...
dragonite3000 Posted July 5, 2018 Share Posted July 5, 2018 2 hours ago, Explv said: @meganide97 what's this? @Muffins @Chris @Night @Mio Poor guy, he gets excited about his first script and you get to airing him out lol. 1 Quote Link to comment Share on other sites More sharing options...
dogetrix Posted July 5, 2018 Share Posted July 5, 2018 @meganide97 The bank will still open because of the statement in the if. in the if statement you have !getBank().open(). The open() method tries to open the bank and returns true or false. This means that the bot will try to open the bank while your code is in the if statement. If the bank opens successfully, it will return true and you won't go to that part of your code again. Therefore calling getBank().open() again inside of the if statement is basically pointless Quote Link to comment Share on other sites More sharing options...
meganide97 Posted July 5, 2018 Author Share Posted July 5, 2018 2 hours ago, dogetrix said: @meganide97 The bank will still open because of the statement in the if. in the if statement you have !getBank().open(). The open() method tries to open the bank and returns true or false. This means that the bot will try to open the bank while your code is in the if statement. If the bank opens successfully, it will return true and you won't go to that part of your code again. Therefore calling getBank().open() again inside of the if statement is basically pointless I see now, thank you! Quote Link to comment Share on other sites More sharing options...
Zylex Posted July 5, 2018 Share Posted July 5, 2018 (edited) Looks very cool! Was it difficult to learn? Edited July 5, 2018 by Zylex Quote Link to comment Share on other sites More sharing options...
lebotman Posted July 5, 2018 Share Posted July 5, 2018 Baller script mate. Quote Link to comment Share on other sites More sharing options...