Jump to content

Inventory Listener


dragon40226
 Share

Recommended Posts

Wanted to Share something that I took from TriBot, and then ported to here.

Inventory Listener watches everything that comes in and out of the Inventory.

This is useful for tracking how many Logs Cut or Ores Mined and whatever else you need.

 

1. Interfaces Needed (Condition and InventoryListener).

Condition.java :

@FunctionalInterface
public interface Condition {

    /**
     * Tracks if the Condition is active or not
     * @return boolean of whether its active or not
     */
    boolean active();

}

InventoryListener.java :

public interface InventoryListener {
    /**
     * When a new item comes into the Inventory, this is invoked.
     * @param item ID of item gained
     * @param count amount of item gained
     */
    void inventoryItemGained(int item, int count);

    /**
     * When a new item goes out of the Inventory, this is invoked.
     * @param item ID of item lost
     * @param count amount of item lost
     */
    void inventoryItemLost(int item, int count);
}

 

InventoryObserver.java :

import xobot.script.methods.tabs.Inventory;
import xobot.script.util.Time;
import xobot.script.wrappers.interactive.Item;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Watches the inventory (for items coming in and going out)
 * Threaded, so it doesnt hog resources
 */
public class InventoryObserver extends Thread {
    private ArrayList<InventoryListener> listeners;
    private Condition condition;

    public InventoryObserver(Condition condition) {
        this.listeners = new ArrayList<>();
        this.condition = condition;
    }

    /**
     * Main Logic
     */
    @Override
    public void run() {

        //Item, Amount
        HashMap<Integer, Integer> map = inventoryHashMap();
        while (true) {
            Time.sleep(100);
            if (!condition.active()) {
                map = inventoryHashMap();
                continue;
            }
            HashMap<Integer, Integer> updatedMap = inventoryHashMap();
            for (int item : updatedMap.keySet()) {
                int countInitial = map.getOrDefault(item, 0), countFinal = updatedMap.get(item);
                if (countFinal > countInitial) {
                    addTrigger(item, countFinal - countInitial);
                } else if (countFinal < countInitial) {
                    subtractedTrigger(item, countInitial - countFinal);
                }
                map.remove(item);
            }
            for (Integer i : map.keySet()) if (!updatedMap.containsKey(i)) subtractedTrigger(i, map.get(i));
            map = updatedMap;
        }
    }

    /**
     * Create new hashmap of current Inventory
     * @return the inventoryHashMap
     */
    private HashMap<Integer, Integer> inventoryHashMap() {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (Item item : Inventory.getItems()) {
            map.put(item.getID(), item.getStack());
        }
        return map;
    }

    /**
     * Adds listener to the list
     * @param inventoryListener listener to add
     */
    public void addListener(InventoryListener inventoryListener) {
        this.listeners.add(inventoryListener);
    }

    /**
     * Trigger invoked when an item is added to the inventory, procs all listeners
     * @param item ID of item that came in
     * @param amount amount of item that came in
     */
    private void addTrigger(int item, int amount) {
        for (InventoryListener l : listeners)
            l.inventoryItemGained(item, amount);
    }
    /**
     * Trigger invoked when an item left the inventory, procs all listeners
     * @param item ID of item that left
     * @param amount amount of item that left
     */
    private void subtractedTrigger(int item, int amount) {
        for (InventoryListener l : listeners)
            l.inventoryItemLost(item, amount);
    }
}

That was the Needed Code to implement.

Here is a basic implementation of how it can be used:

import xobot.script.ActiveScript;
import xobot.script.methods.Bank;

public class DragonLooter extends ActiveScript implements InventoryListener{

    private InventoryObserver inventoryObserver;
    
    private int goldFoundOnFloor;

    @Override
    public boolean onStart() {
        //Don't watch what goes into Inventory when Bank is open
        inventoryObserver = new InventoryObserver(() -> !Bank.isOpen());
        inventoryObserver.addListener(this);
        inventoryObserver.start();
        
        goldFoundOnFloor = 0;

        return true;
    }

    @Override
    public int loop() {
        return 0;
    }

    @Override
    public void onStop() {
        super.onStop();
        //Stop the Thread
        inventoryObserver.interrupt();
    }

    @Override
    public void inventoryItemGained(int item, int count) {
        if (item == 995) {// ID of GP
            goldFoundOnFloor += count;
            System.out.printf("Just Found %d coins on the floor\n", count);
        }
    }

    //Use the same idea as above
    @Override
    public void inventoryItemLost(int item, int count) {

    }
}

Hope it helps someone, Thanks!

- Dragon

Edited by dragon40226
Fixed stack cases
Link to comment
Share on other sites

  • Neo locked this topic
Guest
This topic is now closed to further replies.
 Share

×
×
  • Create New...