Jump to content

GroundItem Monitor | Detect New Ground Items


Recommended Posts

Posted (edited)

Don't know if anyone will use but I needed something with this functionality and came up with this. Any feedback is appreciated, I'm always trying to learn new things.

 

c09d227f82ce2a2b643bb610dc8d087b.gif

 

GroundMonitor.java:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.osbot.rs07.api.model.GroundItem;
import org.osbot.rs07.script.Script;


public abstract class GroundMonitor {
//My implementation filters out items less than price x, but I removed because it was specific to my needs
	private ArrayList<GroundItem> cache = new ArrayList<GroundItem>();
	private Script ctx;

	public GroundMonitorRelease(Script ctx, int valueThreshold) {
		updateContext(ctx);
		update();
	}

	public void updateContext(Script ctx) {
		this.ctx = ctx;
	}

	public abstract void onChange();

	public boolean hasChanged() {
		return getChanges().length > 0;
	}

	public void update() {
		for (GroundItem item : ctx.getGroundItems().getAll()) {
			if (item != null) {
				cache.add(item);
			}
		}
	}

	public GroundItem[] getChanges() {
		List<GroundItem> items = new ArrayList<GroundItem>();
		ArrayList<GroundItem> ci = new ArrayList<GroundItem>();
		int changes = 0;
		for(GroundItem q : ctx.getGroundItems().getAll()){
			if(q != null){
			items.add(q);
			}
		}
		
		for (GroundItem item : items) {
			if (item != null) {
				int id = item.getId();
                if (!contains(ci, id) && !cached(item)) {
                    ci.add(item);
        			changes++;
                }
			}
		}
	
		Collections.sort(ci, new Comparator<GroundItem>(){
			@Override
			public int compare(GroundItem o1, GroundItem o2) {
				 int d0 = CheckPrice.get(o1.getId()); //Use distance instead of price
				 int d1 = CheckPrice.get(o2.getId()); //Use distance instead of price
				   return (d0 < d1 ? -1 :             //It will return the closer one first
		               (d0 == d1 ? 0 : 1));
			}
			
		});
		
		return Arrays.copyOf(ci.toArray(new GroundItem[ci.size()]), changes);
	}
	
	private boolean cached(GroundItem item){
		return cache.contains(item);
	}

	private boolean contains(ArrayList<GroundItem> list, int id) {
		for (GroundItem i : list) {
			if (i == null)
				continue;
			if (i.getId() == id) {
				return true;
			}
		}
		return false;
	}
	
}

Main.java (onStart):

groundMonitor = new GroundMonitor(getScript()) {
				@Override
				public void onChange() {
					for (GroundItem i : getChanges()) {
						if(i != null){
						log(i.getName() + " : " + CheckPrice.get(i.getId()));
						}
					}

				}
			};

Main.java (onPaint):

if (groundMonitor != null && groundMonitor.hasChanged()) {
			groundMonitor.onChange();
			groundMonitor.update();
		}
Edited by LoudPacks
  • Like 4
Posted (edited)

Looks good, you might want to consider using a proper thread instead of the paint thread though. As far as I know the paint thread is executed like 60 times a second, so that's literally every ~16 ms which is not really necessary. If you want to go with the optimisations to the maximum then you can detect the changes every tick instead since we have the possibilities to do so with the current API which would be about 40 times more efficient CPU wise. 

 

VSuShjF.gif

Edited by Token
  • Like 1
Posted (edited)

Dank EDT errors u have there doge.png

what

Looks good, you might want to consider using a proper thread instead of the paint thread though. As far as I know the paint thread is executed like 60 times a second, so that's literally every ~16 ms which is not really necessary. If you want to go with the optimisations to the maximum then you can detect the changes every tick instead since we have the possibilities to do so with the current API which would be about 40 times more efficient CPU wise. 

 

VSuShjF.gif

 

Will something like this suffice?

 monitorThread = new Thread(){
			    public void run() {
			    	inventoryMonitor = new InventoryMonitor(getScript()) {
						@Override
						public void onChange() {
							for (Item i : getChanges()) {
								if(i != null){
								lootCount += i.getAmount();
								lootValue += CheckPrice.get(i.getId());
								}
							}

						}
					};
					
					groundMonitor = new GroundMonitor(getScript(), Settings.lootThresh, Settings.zoneArea) {
						@Override
						public void onChange() {
							for (org.osbot.rs07.api.model.GroundItem i : getChanges()) {
								if(i != null){
								log(i.getName() + " : " + CheckPrice.get(i.getId()));
								}
							}

						}
					};
			    
			    while(!monitorThread.isInterrupted()){
			    	if (inventoryMonitor != null && !getBank().isOpen() && inventoryMonitor.hasChanged()) {
						inventoryMonitor.onChange();
						inventoryMonitor.update();
					}
					
					if (groundMonitor != null && !getBank().isOpen() && groundMonitor.hasChanged()) {
						groundMonitor.onChange();
						groundMonitor.update();
					}
			    }
			    }
			    
				};
				monitorThread.start();
Edited by LoudPacks
Posted
what

 

Will something like this suffice?

 monitorThread = new Thread(){
			    public void run() {
			    	inventoryMonitor = new InventoryMonitor(getScript()) {
						@Override
						public void onChange() {
							for (Item i : getChanges()) {
								if(i != null){
								lootCount += i.getAmount();
								lootValue += CheckPrice.get(i.getId());
								}
							}

						}
					};
					
					groundMonitor = new GroundMonitor(getScript(), Settings.lootThresh, Settings.zoneArea) {
						@Override
						public void onChange() {
							for (org.osbot.rs07.api.model.GroundItem i : getChanges()) {
								if(i != null){
								log(i.getName() + " : " + CheckPrice.get(i.getId()));
								}
							}

						}
					};
			    
			    while(!monitorThread.isInterrupted()){
			    	if (inventoryMonitor != null && !getBank().isOpen() && inventoryMonitor.hasChanged()) {
						inventoryMonitor.onChange();
						inventoryMonitor.update();
					}
					
					if (groundMonitor != null && !getBank().isOpen() && groundMonitor.hasChanged()) {
						groundMonitor.onChange();
						groundMonitor.update();
					}
			    }
			    }
			    
				};
				monitorThread.start();

That should freeze your client because it has no sleeps so the new thread will attempt to use the whole CPU execution cap.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

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