Dextrell Posted June 28 Share Posted June 28 (edited) Hello everyone this is my first script. I'd love to grab some feedback and any progress pictures you guys post would greatly help! This bot supports all trees around draynor village up to yew trees! The source code is here if you guys are sus and the jar link is below for those that want to run it right away! If the GUI is not showing anything just slightly resize it for some reason this is happening if someone knows why please point me in the right direction and I'll fix it! Source Code Spoiler package com.dexcutter; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.URL; import java.text.DecimalFormat; import java.util.Comparator; import java.util.List; import java.util.concurrent.TimeUnit; import javax.imageio.ImageIO; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; 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.RS2Object; import org.osbot.rs07.api.ui.Skill; import org.osbot.rs07.api.ui.Tab; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.ConditionalSleep; @ScriptManifest(author = "Dextrell", info = "Woodcutting Script", name = "DexCutter", version = 0, logo = "") public class DexCutter extends Script { private boolean isRunning; private long timeStarted; private long timeFinished; private long timeElapsed; private int startingXp; private int endedXp; private int xpGained; private int currentXp; private int logsChopped = 0; private int currentLevel; private int startingLevel; private int levelsGained; @SuppressWarnings("unused") private boolean dropLogs; private DecimalFormat df = new DecimalFormat("#"); private Font font = new Font("Consolas", Font.BOLD, 15); // Gui components private JFrame frame; private String[] treeChoices = { "Tree", "Oak tree", "Willow tree", "Yew tree" }; private String[] axeChoices = { "Bronze axe", "Iron axe", "Steel axe", "Black axe", "Adamant axe", "Rune axe", "Dragon axe" }; private String treeSelected = "Yew tree"; private String axeSelected = "Rune axe"; private Tree tree = Tree.TREE; private Area treeArea = tree.getAreas()[0]; private int treeAreaIndex = 0; private boolean ascendingAreas = true; private Image backgroundImage; /** * Regular Tree: 1278 Oak Tree: 10820 */ @Override public void onStart() { log("Initializing Script...."); frame = new JFrame("DexCutter"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setBounds(50, 50, 400, 400); frame.setVisible(true); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); JLabel treeLabel = new JLabel("Select a tree type"); treeLabel.setAlignmentX(Component.CENTER_ALIGNMENT); panel.setSize(400, 400); panel.add(treeLabel); JComboBox<String> treeComboBox = new JComboBox<String>(treeChoices); treeComboBox.setMaximumSize(treeComboBox.getPreferredSize()); treeComboBox.setAlignmentX(Component.CENTER_ALIGNMENT); treeComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub treeSelected = treeComboBox.getSelectedItem().toString(); switch (treeSelected) { case "Tree": tree = Tree.TREE; break; case "Oak tree": tree = Tree.OAK; break; case "Willow tree": tree = Tree.WILLOW; break; case "Yew tree": tree = Tree.YEW; break; default: tree = Tree.TREE; break; } treeArea = tree.getAreas()[0]; } }); JComboBox<String> axeComboBox = new JComboBox<String>(axeChoices); axeComboBox.setMaximumSize(axeComboBox.getPreferredSize()); axeComboBox.setAlignmentX(Component.CENTER_ALIGNMENT); axeComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { axeSelected = (String) axeComboBox.getSelectedItem(); } }); panel.add(treeComboBox); panel.add(axeComboBox); JLabel dropLogsLabel = new JLabel("Drop Logs?"); panel.add(dropLogsLabel); ButtonGroup dropRadioButtonGroup = new ButtonGroup(); JRadioButton yesButton = new JRadioButton(); yesButton.setText("Yes"); // yesButton.setBounds(120, 30, 120, 50); JRadioButton noButton = new JRadioButton(); noButton.setText("No"); // noButton.setBounds(250, 30, 80, 50); noButton.setSelected(true); panel.add(yesButton); panel.add(noButton); dropRadioButtonGroup.add(yesButton); dropRadioButtonGroup.add(noButton); JButton startButton = new JButton("Start"); startButton.setAlignmentX(Component.CENTER_ALIGNMENT); startButton.addActionListener(e -> { dropLogs = yesButton.isSelected(); if (treeSelected == null) { JOptionPane.showMessageDialog(null, "Error: Tree type not selected!"); } else { isRunning = true; timeStarted = System.currentTimeMillis(); startingXp = skills.getExperience(Skill.WOODCUTTING); startingLevel = skills.getStatic(Skill.WOODCUTTING); frame.dispose(); } }); panel.add(startButton); frame.add(panel); backgroundImage = getImage("https://iili.io/dFKcgGR.png"); } @Override public int onLoop() throws InterruptedException { if (isRunning) { if (!getInventory().isFull() && !treeArea.contains(myPlayer())) { if (getWalking().webWalk(treeArea)) { log("Walking to trees..."); if (settings.getRunEnergy() >= 70) { settings.setRunning(true); } new ConditionalSleep(8000, 10000) { @Override public boolean condition() throws InterruptedException { return false; } }; } } else if (!getInventory().isFull()) { chopTree(); } else { log("Inventory full."); // Walks to the bank. bankInventory(); } int randVal = random(0, 1000); if (randVal == 25) { log(randVal + " open friends"); openFriends(); } } return random(200, 300); } @Override public void onExit() { log("Thank you for using DexCutter!"); timeFinished = System.currentTimeMillis(); endedXp = skills.getExperience(Skill.WOODCUTTING); log("Time Finished: " + timeFinished + " Exp Gathered: " + endedXp); } @Override public void onPaint(Graphics2D g) { if (isRunning) { g.setFont(font); g.setFont(g.getFont().deriveFont(15.0f)); g.setColor(Color.RED); timeElapsed = System.currentTimeMillis() - this.timeStarted; if(backgroundImage != null) g.drawImage(backgroundImage, 0, 340, null); g.drawString("Time ran for:", 40, 395); g.drawString(ft(timeElapsed), 150, 395); currentXp = skills.getExperience(Skill.WOODCUTTING); xpGained = currentXp - startingXp; currentLevel = skills.getStatic(Skill.WOODCUTTING); g.drawString("Xp Gained:" + xpGained, 40, 420); levelsGained = currentLevel - startingLevel; g.drawString("Levels gained:" + levelsGained, 260, 420); logsChopped = (int) (xpGained / tree.getExperience()); g.drawString("Logs chopped:" + df.format(logsChopped), 40, 445); } } private String ft(long duration) // Makes time 0:0:0 { 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; } private void chopTree() { // log("Finding tree: " + treeObject); // tree // to chop. // log(tree.getAreas().length); if (!myPlayer().isAnimating() && !myPlayer().isMoving()) { // RS2Object treeObject = getObjects() // .closest(obj -> obj != null && obj.getName().equals(treeSelected)); // What RS2Object treeObject = getObjects().closest(tree.getObjectId()); if (treeObject == null) { this.log("Yew tree is null...."); } log("does it contain tree obj? " + treeArea.contains(treeObject)); if (treeObject != null && treeArea.contains(treeObject)) { log("Chopping tree: " + treeObject.toString()); if (treeObject.interact("Chop down")) { int min = tree.getMinTime(); int max = tree.getMaxTime(); new ConditionalSleep(max, min) { @Override public boolean condition() throws InterruptedException { return false; } }.sleep(); } } else { // If it doesn't see a tree it moves the camera and then moves. // getCamera().toEntity(treeObject); log("Searching for a tree..."); if (treeAreaIndex == 0) { ascendingAreas = true; log("We are ascending"); } else if (treeAreaIndex == tree.getAreas().length - 1) { ascendingAreas = false; log("We are goin down"); } if (tree.getAreas().length > 0) { // log("BEFORE new tree area: " + treeAreaIndex); treeArea = ascendingAreas ? tree.getAreas()[treeAreaIndex++] : tree.getAreas()[treeAreaIndex--]; log("Setting new tree area..."); log("Found new tree area: " + treeAreaIndex); } else { log("Rotating camera to: " + treeObject); if (getCamera().toEntity(treeObject)) { log("Chopping tree: " + treeObject); treeObject.interact("Chop down"); int min = tree.getMinTime(); int max = tree.getMaxTime(); new ConditionalSleep(max, min) { @Override public boolean condition() throws InterruptedException { return false; } }.sleep(); } } } } } public RS2Object getClosestObject(Script script, Position position) { List<RS2Object> regionObjects = script.objects.getAll(); if (regionObjects.size() == 0) { script.log("No objects found"); return null; } else if (regionObjects.size() == 1) { return regionObjects.get(0); } regionObjects.sort(new Comparator<RS2Object>() { @Override public int compare(RS2Object o1, RS2Object o2) { return o1.getPosition().distance(position) - o2.getPosition().distance(position); } }); return regionObjects.get(0); } private void bankInventory() { // ascendingAreas = true; // treeAreaIndex = 0; if (getWalking().webWalk(Banks.DRAYNOR)) { // What bank it banks at. log("Walking to bank..."); new ConditionalSleep(5000, 1000) { @Override public boolean condition() throws InterruptedException { return true; } }; RS2Object depoBox = objects.closest("Bank deposit box"); // Opens deposit box and deposits logs. if (depoBox != null) { new ConditionalSleep(2000, 5000) { @Override public boolean condition() throws InterruptedException { return depoBox.isVisible(); } }; if (depoBox.interact("Deposit")) { while (!depositBox.isOpen()) { new ConditionalSleep(2000, 5000) { @Override public boolean condition() throws InterruptedException { return true; } }; } depositBox.depositAllExcept(axeSelected); treeAreaIndex = 0; // start from the first tree closest to the bank } } } } public void openInventory() { getTabs().open(Tab.INVENTORY); new ConditionalSleep(450, 3000) { @Override public boolean condition() throws InterruptedException { return getTabs().getOpen().equals(Tab.INVENTORY); } }.sleep(); } public void openFriends() { getTabs().open(Tab.FRIENDS); new ConditionalSleep(450, 3000) { @Override public boolean condition() throws InterruptedException { return getTabs().getOpen().equals(Tab.FRIENDS); } }.sleep(); openInventory(); } private Image getImage(String url) // Get's the background image. { try { log("image read"); return ImageIO.read(new URL(url)); } catch (IOException e) { e.printStackTrace(); } return null; } } package com.dexcutter; import org.osbot.rs07.api.map.Area; public enum Tree { TREE("Tree", 25, 1278, 2000, 8000, new Area[]{new Area(3146, 3228, 3204, 3213)}), OAK("Oak tree", 10820, 37.5, 8000, 10000, new Area[] {new Area(3146, 3228, 3164, 3213)}), WILLOW("Willow tree", 8481, 67.5, 10000, 13000, new Area[] {new Area(3087, 3225, 3092, 3239)}), YEW("Yew tree", 10822, 175, 15000, 20000, new Area[] {new Area(3145,3251,3150,3257), new Area(3150, 3223, 3154, 3230), new Area(3164, 3218, 3168, 3222), new Area(3183, 3224, 3188, 3228)}); private String name; private int objectId; private double experience; private int minTime; private int maxTime; private Area[] areas; private Tree(String name, int objectId, double experience, int minTime, int maxTime, Area[] areas) { this.name = name; this.objectId = objectId; this.experience = experience; this.minTime = minTime; this.maxTime = maxTime; this.areas = areas; } public String getName() { return this.name; } public int getObjectId() { return this.objectId; } public double getExperience() { return this.experience; } public int getMinTime() { return minTime; } public int getMaxTime() { return maxTime; } public Area[] getAreas() { return this.areas; } } Media Spoiler https://freeimage.host/i/dFKE4xn Jar Download Spoiler https://fastupload.io/a4cfdf195f5e2ba0 Edited June 28 by Dextrell Quote Link to comment Share on other sites More sharing options...
yfoo Posted June 29 Share Posted June 29 (edited) 1. Put the image in resources so that a network request is not needed then use SystemIO to get thz. There is no guarantee that the hosting service won't delete your image randomly. Refer to the link below for a more concise tutorial. RS2Object treeObject = getObjects().closest(tree.getObjectId()); if (treeObject == null) { this.log("Yew tree is null...."); } log("does it contain tree obj? " + treeArea.contains(treeObject)); 2. Use the filter API. This can be simplified to something like ``` RS2Object treeObject = getObjects().closest(rs2Object -> rs2Object.getId() == tree.getObjectId() && treeArea.contains(rs2Object); ``` This will ensure tree interactions are only done on trees of a certain type (regular, oak, willow, ect.) and are in the designated area. 3. The Paint and GUI are crammed in the the Script class its hard to read. Consider splitting these up into individual classes. You can designate a painter class by having it implement Painter. Then in onStart calling getBot().addPainter(<paint instance>) Make sure to remove this in onStop with getBot().removePainter(<same instance as above>) Otherwise the paint may not get cleaned up if the script crashes/exits. 4. You don't need to call this if you are intending to immediately interact with the object. The interaction will do this if the object is not on screen. if (getCamera().toEntity(treeObject)) Its a great first attempt. Ill take a look at the gui later. Edited June 29 by yfoo 1 Quote Link to comment Share on other sites More sharing options...
yfoo Posted June 30 Share Posted June 30 As for the GUI error public void onStart() { log("Initializing Script...."); frame = new JFrame("DexCutter"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setBounds(50, 50, 400, 400); frame.setVisible(true); //<<<<<<<<<<<<<<<<< ... Move frame.setVisible(true); to the end of onStart(). It is set to visible before al the other components are added to the panel. 1 Quote Link to comment Share on other sites More sharing options...
Dextrell Posted July 1 Author Share Posted July 1 On 6/29/2024 at 5:20 PM, yfoo said: 1. Put the image in resources so that a network request is not needed then use SystemIO to get thz. There is no guarantee that the hosting service won't delete your image randomly. Refer to the link below for a more concise tutorial. RS2Object treeObject = getObjects().closest(tree.getObjectId()); if (treeObject == null) { this.log("Yew tree is null...."); } log("does it contain tree obj? " + treeArea.contains(treeObject)); 2. Use the filter API. This can be simplified to something like ``` RS2Object treeObject = getObjects().closest(rs2Object -> rs2Object.getId() == tree.getObjectId() && treeArea.contains(rs2Object); ``` This will ensure tree interactions are only done on trees of a certain type (regular, oak, willow, ect.) and are in the designated area. 3. The Paint and GUI are crammed in the the Script class its hard to read. Consider splitting these up into individual classes. You can designate a painter class by having it implement Painter. Then in onStart calling getBot().addPainter(<paint instance>) Make sure to remove this in onStop with getBot().removePainter(<same instance as above>) Otherwise the paint may not get cleaned up if the script crashes/exits. 4. You don't need to call this if you are intending to immediately interact with the object. The interaction will do this if the object is not on screen. if (getCamera().toEntity(treeObject)) Its a great first attempt. Ill take a look at the gui later. Thank you so much for the useful insight I'll make those changes! You're right about the painter thank you so much for the tips! Quote Link to comment Share on other sites More sharing options...