Apaec Posted September 9, 2015 Share Posted September 9, 2015 (edited) 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: 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 May 24, 2016 by Apaec 4 Quote Link to comment Share on other sites More sharing options...
fixthissite Posted September 10, 2015 Share Posted September 10, 2015 (edited) 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 Edited September 13, 2015 by fixthissite 1 Quote Link to comment Share on other sites More sharing options...
Apaec Posted September 10, 2015 Author Share Posted September 10, 2015 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 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 Quote Link to comment Share on other sites More sharing options...
Joseph Posted September 13, 2015 Share Posted September 13, 2015 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 Quote Link to comment Share on other sites More sharing options...
Apaec Posted September 13, 2015 Author Share Posted September 13, 2015 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 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 Quote Link to comment Share on other sites More sharing options...
Joseph Posted September 13, 2015 Share Posted September 13, 2015 so it returns the name and its position? Quote Link to comment Share on other sites More sharing options...
Apaec Posted September 13, 2015 Author Share Posted September 13, 2015 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 Quote Link to comment Share on other sites More sharing options...