Jump to content

DexCutter - F2P Woodcutting Script


Recommended Posts

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

 

Jar Download

 

Edited by Dextrell
Link to comment
Share on other sites

 

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 by yfoo
  • Heart 1
Link to comment
Share on other sites

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. 

  • Heart 1
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...