Jump to content

Object loading class with snippet and appropriate implementation


Apaec

Recommended Posts

I wrote this object loader class to make a personal aio woodcutting script. I thought i'd share it with you guys 

 

Hope something can be learnt from this

 

ObjectLoader class:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.DefaultListModel;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import javax.swing.JList;

import org.osbot.rs07.api.map.Position;
import org.osbot.rs07.api.model.RS2Object;
import org.osbot.rs07.script.Script;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.JTextField;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class ObjectLoader extends JFrame {

	/**
	 * @author Apaec
	 */

	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private String interactionString;
	private int radius = 10;

	private final DefaultListModel<String> modelDesired = new DefaultListModel<String>();
	private final DefaultListModel<String> modelLoaded = new DefaultListModel<String>();
	private ArrayList<RS2Object> objectListDesired = new ArrayList<RS2Object>();
	private ArrayList<RS2Object> objectListLoaded = new ArrayList<RS2Object>();
	private ArrayList<Position> controlPos = new ArrayList<Position>();
	private boolean isVisible = false;

	public ObjectLoader(final Script script, String defaultSearchString,
			int defaultRadius) {
		this.interactionString = defaultSearchString;
		this.radius = defaultRadius;
	}

	public void openLoader(final Script script) {

		setTitle("Object Loader");
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 450, 305);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		setAlwaysOnTop(true);
		setResizable(false);

		JLabel lblLoadObjectsWithin = new JLabel("Load objects within radius:");
		JLabel lblLoadObjectsWith = new JLabel("Load objects with action:\r\n");
		final JSpinner spinner = new JSpinner();
		final JTextField txtChopDown = new JTextField(interactionString);
		JScrollPane scrollPane = new JScrollPane();
		final JList<String> desiredtemsList = new JList<String>(modelDesired);
		JLabel lblDesiredObjects = new JLabel("Desired Objects");
		JScrollPane scrollPane_1 = new JScrollPane();
		final JList<String> loadedItemsList = new JList<String>(modelLoaded);
		JLabel lblNewLabel = new JLabel("Loaded Local Objects");
		JButton btnNewButton = new JButton("<<");
		JButton button = new JButton(">>");
		JButton btnRefresh = new JButton("Refresh");
		JButton btnSave = new JButton("Save");

		lblLoadObjectsWithin.setBounds(10, 11, 193, 14);
		lblLoadObjectsWith.setBounds(10, 36, 193, 14);
		txtChopDown.setBounds(213, 33, 215, 20);
		btnNewButton.setBounds(192, 61, 54, 69);
		button.setBounds(192, 134, 54, 69);
		btnRefresh.setBounds(10, 214, 89, 42);
		btnSave.setBounds(109, 214, 319, 42);
		spinner.setBounds(213, 8, 215, 20);
		scrollPane.setBounds(10, 61, 178, 142);
		scrollPane_1.setBounds(250, 61, 178, 142);

		txtChopDown.setHorizontalAlignment(SwingConstants.CENTER);
		txtChopDown.setColumns(10);
		lblDesiredObjects.setHorizontalAlignment(SwingConstants.CENTER);
		lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
		scrollPane.setViewportView(desiredtemsList);
		scrollPane.setColumnHeaderView(lblDesiredObjects);
		scrollPane_1.setViewportView(loadedItemsList);
		scrollPane_1.setColumnHeaderView(lblNewLabel);
		spinner.setModel(new SpinnerNumberModel(radius, 1, 30, 1));

		contentPane.add(lblLoadObjectsWithin);
		contentPane.add(spinner);
		contentPane.add(lblLoadObjectsWith);
		contentPane.add(txtChopDown);
		contentPane.add(scrollPane);
		contentPane.add(scrollPane_1);
		contentPane.add(btnNewButton);
		contentPane.add(button);
		contentPane.add(btnRefresh);
		contentPane.add(btnSave);

		setVisible(true);
		isVisible = true;

		spinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent arg0) {
				radius = (int) spinner.getValue();
			}
		});

		txtChopDown.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				interactionString = txtChopDown.getText();
			}

			public void insertUpdate(DocumentEvent arg0) {
				interactionString = txtChopDown.getText();
			}

			public void removeUpdate(DocumentEvent arg0) {
				interactionString = txtChopDown.getText();
			}
		});

		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (loadedItemsList.getSelectedIndex() != -1) {
					modelDesired
							.addElement(convertObjectToString(objectListLoaded
									.get(loadedItemsList.getSelectedIndex())));
					objectListDesired.add(objectListLoaded.get(loadedItemsList
							.getSelectedIndex()));
					objectListLoaded.remove(loadedItemsList.getSelectedIndex());
					modelLoaded.removeElementAt(loadedItemsList
							.getSelectedIndex());
				}
			}
		});

		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (desiredtemsList.getSelectedIndex() != -1) {
					modelLoaded
							.addElement(convertObjectToString(objectListDesired
									.get(desiredtemsList.getSelectedIndex())));
					objectListLoaded.add(objectListDesired.get(desiredtemsList
							.getSelectedIndex()));
					objectListDesired.remove(desiredtemsList.getSelectedIndex());
					modelDesired.removeElementAt(desiredtemsList
							.getSelectedIndex());
				}
			}
		});

		btnRefresh.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				clearListsAndModels();
				ArrayList<RS2Object> objectsAll = null;
				objectsAll = loadNearbyObjectsForActionAsList(script,
						getRadius(), getInteractionString(), true);
				if (objectsAll != null) {
					for (RS2Object o : objectsAll)
						modelLoaded.addElement(convertObjectToString(o));
					objectListLoaded = objectsAll;
				}
			}
		});

		btnSave.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				setVisible(false);
				isVisible = false;
			}
		});
	}

	public String convertObjectToString(RS2Object o) {
		return o.getName() + " (" + o.getPosition().getX() + ","
				+ o.getPosition().getY() + "," + o.getPosition().getZ() + ")";
	}

	public String getInteractionString() {
		return interactionString;
	}

	public int getRadius() {
		return radius;
	}

	public void clearListsAndModels() {
		modelLoaded.clear();
		modelDesired.clear();
		objectListDesired.clear();
		objectListLoaded.clear();
		controlPos.clear();
	}

	public boolean isOpen() {
		return isVisible;
	}

	public RS2Object[] getAllObjects() {
		if (objectListLoaded.size() > 0) {
			RS2Object[] objects = new RS2Object[objectListLoaded.size()];
			for (RS2Object o : objectListLoaded)
				objects[objectListLoaded.indexOf(o)] = o;
			return objects;
		} else {
			return null;
		}
	}

	public RS2Object[] getDesiredObjects() {
		if (objectListDesired.size() > 0) {
			RS2Object[] objects = new RS2Object[objectListDesired.size()];
			for (RS2Object o : objectListDesired)
				objects[objectListDesired.indexOf(o)] = o;
			return objects;
		} else {
			return null;
		}
	}

	private ArrayList<RS2Object> loadNearbyObjectsForActionAsList(
			Script script, int radius, String action, boolean clearLists) {
		if (clearLists)
			clearListsAndModels();
		ArrayList<RS2Object> objects = new ArrayList<RS2Object>();
		for (RS2Object r : script.objects.getAll()) {
			if (r != null && r.exists() && !r.getName().equals("null")
					&& script.map.distance(r) <= radius
					&& !controlPos.contains(r.getPosition())) {
				if (action.equals("")) {
					controlPos.add(r.getPosition());
					objects.add(r);
				} else if (r.hasAction(action)) {
					controlPos.add(r.getPosition());
					objects.add(r);
				}
			}
		}
		return objects.size() > 0 ? objects : null;
	}
}
 

>>apologies for the poor jframe code, used a gui builder. Did my best to tidy it up somewhat but I understand it's still a little messy.

 

How to use it in an example script:

import org.osbot.rs07.api.model.RS2Object;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;

@ScriptManifest(name = "Object loader demo", author = "Apaec", version = 1.0, info = "Demo displayin object loader", logo = "")
public class ObjectLoaderDemo extends Script {

	ObjectLoader loader;
	RS2Object[] desiredObjects = null;

	public void onStart() {
		loader = new ObjectLoader(this, "", 10);
		if (!loader.isOpen())
			loader.openLoader(this);
	}

	public int onLoop() throws InterruptedException {
		while (loader.isOpen()) {
			sleep(400);
			desiredObjects = loader.getDesiredObjects();
		}
		// visual debug:
		if (desiredObjects.length > 0)
			for (RS2Object o : desiredObjects)
				if (o != null && o.exists())
					log(o.getName());
		return 10;
	}

	public void onExit() {
		if (loader.isOpen())
			loader.dispose();
	}
} 

Where desiredObjects is your array containing the objects configured by the user.

 

Screenshots:

Gif:

0a473941d145c82b57c0c31942d460c1.gif

 

ZhMx8Vv.gif

 

bcsODwb.png

 

If you're commenting on my code, please be constructive, and I understand it's a bit below-par in places. I know how it is tho when posting snippets x)

 

how it helps

apa

Edited by Apaec
  • Like 4
Link to comment
Share on other sites

Good luck with official scripter status! Here are some tips to help improve your code:

Use lambdas for your action and change listeners. It's less verbose and more efficient.

Don't extend JFrame, as that floods the API of ObjectLoader with a bunch of irrelevant inherited methods (and ObjectLoader is not a frame, it has a frame).

Return Collections, not arrays. This allows easy stream usage and implementation-specific looping through forEach. Although devs can use Arrays.stream(T[]), chances are they'd rather turn it into a collection and use it as such. Only use arrays if you want devs to be able to easily add items at a specific index (without needing to manually fill the collection up to that index).

Do not return null. Read the null section of this thread (http://osbot.org/forum/topic/81558-some-java-tips/)

Use forEach loops for implementation-specific loops:

objectListLoaded.forEach(o -> objects[objectListLoaded.indexOf(o)] = o);
No need for an isVisible variable, as JFrame has an isVisible() method.

It seems you hide the frame, but never dispose it. Dispose it when it's no longer needed.

Why do you pass Script to the constructor of ObjectLoader and openLoader?

If you want some more tips, feel free to message me! If you don't understand anything I've said above, let me know smile.png

Edited by fixthissite
  • Like 1
Link to comment
Share on other sites

Good luck with official scripter status! Here are some tips to help improve your code:

Use lambdas for your action and change listeners. It's less verbose and more efficient.

Don't extend JFrame, as that floods the API of ObjectLoader with a bunch of irrelevant inherited methods (and ObjectLoader is not a frame, it has a frame).

Return Collections, not arrays. This allows easy stream usage and implementation-specific looping through forEach. Although devs can use Arrays.stream(T[]), chances are they'd rather turn it into a collection and use it as such. Only use arrays if you want devs to be able to easily add items at a specific index (without needing to manually fill the collection up to that index).

Do not return null. Read the null section of this thread.

Use forEach loops for implementation-specific loops:

objectListLoaded.forEach(o -> objects[objectListLoaded.indexOf(o)] = o);

No need for an isVisible variable, as JFrame has an isVisible() method.

It seems you hide the frame, but never dispose it. Dispose it when it's no longer needed.

Why do you pass Script to the constructor of ObjectLoader and openLoader?

If you want some more tips, feel free to message me! If you don't understand anything I've said above, let me know smile.png

 

Hey

 

Cheers for the advice :)

As I said, I created the frame and stuff with a windowbuilder which includes the actionlisteners. I could have used lambdas but the code was already generated as such so I was happy enough to leave it as is x)

 

When I created the class in eclipse I created it as a jframe structured class courtesy of the wb plugin. This is why the whole class extends jframe - When i tidied the code up I didn't get around to sorting that out after adding additional methods to the class :) but I agree, that's something I shoulda done

 

As for the other suggestions... it looks like i should put more effort into tidying up my code haha :) I made it hide the gui when you press save because in future i'm planning on making it re-openable with the pre-recorded data

 

Thanks again for the suggestions. Will try and clean the code up some more )

 

apa

Edit:

 

updated code to tidy it up a bit. didn't have much time this morning as i've gotta head out early

 

edited original post

 

apa

edit 2: looks like i fukd something up, will revert it back to old code and then update it when i'm not time pressured when i'm back home

 

apa

Link to comment
Share on other sites

I'm a little confused, after you load the entitys and select the ones you want. What do you save?

You should use eclipse windowbuilder. By the way nice util. I myself have one, divine utility. I want to let you know that jList returns a list of selected items. Meaning that you could select 2 or more entitys and be able to add/remove them at once. Only if you use a for loop when adding/removing.

I would also like the idea if you were able to switch btw npc and rs2objec.

Also I'm a pro with windowbuilder so if you need help :). GL on rank

Link to comment
Share on other sites

I'm a little confused, after you load the entitys and select the ones you want. What do you save?

You should use eclipse windowbuilder. By the way nice util. I myself have one, divine utility. I want to let you know that jList returns a list of selected items. Meaning that you could select 2 or more entitys and be able to add/remove them at once. Only if you use a for loop when adding/removing.

I would also like the idea if you were able to switch btw npc and rs2objec.

Also I'm a pro with windowbuilder so if you need help smile.png. GL on rank

 

 

Hey!

 

ty

 

I actually do use windowbuilder pro, but to make things look a tiny bit more readable (which I failed to achieve, lol), I moved the statements around a bit.

 

I've used divine util too btw, it's nice :) have my own pathrecorder too tho.

 

And you just save a list containing the rs2objects you want.

 

apa

Link to comment
Share on other sites

so it returns the name and its position?

 

No, it returns a RS2Object[] array containing the objects you selected. Not the best way to return them,as fixthissite said I should probably save it as a collection but this is how it is xd

 

You can then get it to return the name and position seperately tho c:

 

apa

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...