package org.rsbot.script.methods;
import org.rsbot.script.wrappers.RSComponent;
import org.rsbot.script.wrappers.RSItem;
import org.rsbot.script.wrappers.RSObject;
import org.rsbot.script.wrappers.RSTile;
import java.awt.*;
import java.util.LinkedList;
/**
* Inventory related operations.
*
* @author Timer
*/
public class Inventory extends MethodProvider {
public static final int INTERFACE_INVENTORY = 679;
public static final int INTERFACE_INVENTORY_PRICE_CHECK = 204;
public static final int INTERFACE_INVENTORY_SHOP = 621;
public static final int INTERFACE_INVENTORY_EQUIPMENT_BONUSES = 670;
public static final int INTERFACE_INVENTORY_BANK = 763;
public static final int INTERFACE_INVENTORY_DEPOSIT_BOX = 11;
public static final int INTERFACE_INVENTORY_DUNGEONEERING_SHOP = 957;
Inventory(final MethodContext ctx) {
super(ctx);
}
/**
* Left-clicks on the selected item.
*
* @return <tt>true</tt> if item was selected, </tt>false</tt> if not.
* @see #clickSelectedItem(boolean)
*/
public boolean clickSelectedItem() {
return clickSelectedItem(true);
}
/**
* Clicks selected inventory item, if it's selected.
*
* @param leftClick <tt>true</tt> for left button click, <tt>false</tt> for right
* button.
* @return <tt>true</tt> if item was selected, <tt>false</tt> if not.
*/
public boolean clickSelectedItem(final boolean leftClick) {
final RSItem item = getSelectedItem();
return item != null && item.doClick(true);
}
/**
* Checks whether or not your inventory contains the provided item ID.
*
* @param itemID The item(s) you wish to evaluate.
* @return <tt>true</tt> if your inventory contains an item with the ID
* provided; otherwise <tt>false</tt>.
* @see #containsOneOf(int...)
* @see #containsAll(int...)
*/
public boolean contains(final int itemID) {
return getItem(itemID) != null;
}
/**
* Checks whether or not your inventory contains the provided item name.
*
* @param name The item(s) you wish to evaluate.
* @return <tt>true</tt> if your inventory contains an item with the name
* provided; otherwise <tt>false</tt>.
*/
public boolean contains(final String name) {
return getItem(name) != null;
}
/**
* Checks whether or not your inventory contains all of the provided item
* IDs.
*
* @param itemID The item(s) you wish to evaluate.
* @return <tt>true</tt> if your inventory contains at least one of all of
* the item IDs provided; otherwise <tt>false</tt>.
* @see #containsOneOf(int...)
*/
public boolean containsAll(final int... itemID) {
for (final int i : itemID) {
if (getItem(i) == null) {
return false;
}
}
return true;
}
/**
* Checks whether or not your inventory contains at least one of the
* provided item IDs.
*
* @param itemID The item ID to check for.
* @return <tt>true</tt> if inventory contains one of the specified items;
* otherwise <tt>false</tt>.
* @see #containsAll(int...)
*/
public boolean containsOneOf(final int... itemID) {
for (final RSItem item : getItems()) {
for (final int i : itemID) {
if (item.getID() == i) {
return true;
}
}
}
return false;
}
/**
* Destroys any inventory items with the given ID.
*
* @param itemID The ID of items to destroy.
* @return <tt>true</tt> if the items were destroyed; otherwise
* <tt>false</tt>.
*/
public boolean destroyItem(final int itemID) {
RSItem item = getItem(itemID);
if (item == null || !item.hasAction("Destroy")) {
return false;
}
while ((item = getItem(itemID)) != null) {
if (methods.interfaces.get(94).isValid()) {
methods.interfaces.getComponent(94, 3).doClick();
} else {
item.interact("Destroy");
}
sleep(random(700, 1100));
}
return true;
}
/**
* Drops all items except those with one of the provided IDs.
* This method drops items vertically going down the inventory.
*
* @param ids The item IDs to drop.
* @return <tt>true</tt> if items were dropped from the inventory;
* otherwise <tt>false</tt>.
* @see #dropAllExcept(boolean, int...)
*/
public boolean dropAllExcept(final int... ids) {
return dropAllExcept(false, ids);
}
/**
* Drops all items except those with one of the provided IDs.
*
* @param leftToRight <tt>true</tt> to drop items from left to right.
* @param ids The item IDs to drop
* @return <tt>true</tt> if items were dropped from the inventory;
* otherwise <tt>false</tt>.
*/
public boolean dropAllExcept(final boolean leftToRight, final int... ids) {
final int startCount = getCount();
final RSTile startLocation = methods.players.getMyPlayer().getLocation();
boolean found_droppable = true;
while (found_droppable && getCountExcept(ids) != 0) {
if (methods.calc.distanceTo(startLocation) > 100) {
break;
}
found_droppable = false;
for (int j = 0; j < 28; j++) {
final int c = leftToRight ? j % 4 : j / 7;
final int r = leftToRight ? j / 4 : j % 7;
final RSItem curItem = getItems()[c + r * 4];
if (curItem != null) {
int id = curItem.getID();
if (id != -1) {
boolean isInItems = false;
for (final int i : ids) {
if (i == id) {
isInItems = true;
break;
}
}
if (!isInItems) {
for (int d = 0; d < 3; d++) {
if (dropItem(c, r)) {
found_droppable = true;
break;
}
sleep(random(100, 400));
}
}
}
}
}
sleep(random(400, 800));
}
return getCount() < startCount;
}
/**
* Drops all items matching the given ids
*
* @param ids item ids to drop
* @return <tt>true</tt> if all items were dropped; otherwise <tt>false</tt>
*/
public boolean dropAll(final int... ids) {
for (final RSItem i : getItems(ids)) {
if (i != null) {
dropItem(i);
}
}
return !containsOneOf(ids);
}
/**
* Empties the inventory (Drops all items)
*
* @param leftToRight leftToRight <tt>true</tt> to drop items from left to right.
* @return <tt>true</tt> if items were dropped from the inventory;
* otherwise <tt>false</tt>.
*/
public boolean empty(boolean leftToRight) {
return dropAllExcept(leftToRight, new int[]{});
}
/**
* Empties the inventory (Drops all items)
*
* @return <tt>true</tt> if items were dropped from the inventory;
* otherwise <tt>false</tt>.
*/
public boolean empty() {
return empty(false);
}
/**
* Drops the item in the specified column and row.
*
* @param col The column the item is in.
* @param row The row the item is in.
* @return <tt>true</tt> if we tried to drop the item,
* <tt>false</tt> if not (e.g., if item is undroppable)
*/
public boolean dropItem(final int col, final int row) {
if (methods.interfaces.canContinue()) {
methods.interfaces.clickContinue();
sleep(random(800, 1300));
}
if (methods.game.getTab() != Game.Tab.INVENTORY
&& !methods.interfaces.get(Bank.INTERFACE_BANK).isValid()
&& !methods.interfaces.get(Store.INTERFACE_STORE).isValid()) {
methods.game.openTab(Game.Tab.INVENTORY);
}
if (col < 0 || col > 3 || row < 0 || row > 6) {
return false;
}
final RSItem item = getItems()[col + row * 4];
return item != null && item.getID() != -1 && item.interact("Drop");
}
/**
* Drops the given RSItem
*
* @param item RSItem to drop.
* @return <tt>true</tt> if we tried to drop the item,
* <tt>false</tt> if not (e.g., if item is undroppable)
*/
public boolean dropItem(final RSItem item) {
if (methods.interfaces.canContinue()) {
methods.interfaces.clickContinue();
sleep(random(800, 1300));
}
if (methods.game.getTab() != Game.Tab.INVENTORY
&& !methods.interfaces.get(Bank.INTERFACE_BANK).isValid()
&& !methods.interfaces.get(Store.INTERFACE_STORE).isValid()) {
methods.game.openTab(Game.Tab.INVENTORY);
}
return item != null && item.getID() != -1 && item.interact("Drop");
}
/**
* Drops the first item that matches the given id
*
* @param id id of the item.
* @return <tt>true</tt> if we tried to drop the item,
* <tt>false</tt> if not (e.g., if item is undroppable)
*/
public boolean dropItem(final int id) {
if (methods.interfaces.canContinue()) {
methods.interfaces.clickContinue();
sleep(random(800, 1300));
}
if (methods.game.getTab() != Game.Tab.INVENTORY
&& !methods.interfaces.get(Bank.INTERFACE_BANK).isValid()
&& !methods.interfaces.get(Store.INTERFACE_STORE).isValid()) {
methods.game.openTab(Game.Tab.INVENTORY);
}
RSItem item = getItem(id);
return item != null && item.getID() != -1 && item.interact("Drop");
}
/**
* Gets the count of all items in your inventory, ignoring stack sizes.
*
* @return The count.
*/
public int getCount() {
return getCount(false);
}
/**
* Gets the count of all items in your inventory.
*
* @param includeStacks <tt>false</tt> if stacked items should be counted as a
* single item; otherwise <tt>true</tt>.
* @return The count.
*/
public int getCount(final boolean includeStacks) {
int count = 0;
for (final RSItem item : getItems()) {
final int iid = item.getID();
if (iid != -1) {
if (includeStacks) {
count += item.getStackSize();
} else {
++count;
}
}
}
return count;
}
/**
* Gets the count of all the items in the inventory with the any of the
* specified IDs. This ignores stack sizes.
*
* @param itemIDs the item IDs to include
* @return The count.
*/
public int getCount(final int... itemIDs) {
return getCount(false, itemIDs);
}
/**
* Gets the count of all the items in the inventory with the any of the
* specified IDs.
*
* @param includeStacks <tt>true</tt> to count the stack sizes of each item;
* <tt>false</tt> to count a stack as a single item.
* @param itemIDs the item IDs to include
* @return The count.
*/
public int getCount(final boolean includeStacks, final int... itemIDs) {
int total = 0;
for (final RSItem item : getItems()) {
if (item == null) {
continue;
}
for (final int ID : itemIDs) {
if (item.getID() == ID) {
total += includeStacks ? item.getStackSize() : 1;
}
}
}
return total;
}
/**
* Gets the count of all the items in the inventory without any of the
* provided IDs, ignoring stack sizes.
*
* @param ids The item IDs to exclude.
* @return The count.
*/
public int getCountExcept(final int... ids) {
return getCountExcept(false, ids);
}
/**
* Gets the count of all the items in the inventory without any of the
* provided IDs.
*
* @param includeStacks <tt>true</tt> to count the stack sizes of each item;
* <tt>false</tt> to count a stack as a single item.
* @param ids The item IDs to exclude.
* @return The count.
*/
public int getCountExcept(final boolean includeStacks, final int... ids) {
int count = 0;
for (final RSItem i : getItems()) {
if (i.getID() != -1) {
boolean skip = false;
for (final int id : ids) {
if (i.getID() == id) {
skip = true;
break;
}
}
if (!skip) {
count += includeStacks ? i.getStackSize() : 1;
}
}
}
return count;
}
/**
* Gets the first item in the inventory with any of the provided IDs.
*
* @param ids The IDs of the item to find.
* @return The first <tt>RSItem</tt> for the given IDs; otherwise null.
*/
public RSItem getItem(final int... ids) {
for (final RSItem item : getItems()) {
for (final int id : ids) {
if (item.getID() == id) {
return item;
}
}
}
return null;
}
/**
* Gets the first item in the inventory containing any of the provided names.
*
* @param names The names of the item to find.
* @return The first <tt>RSItem</tt> for the given name(s); otherwise null.
*/
public RSItem getItem(final String... names) {
for (final RSItem item : getItems()) {
String name = item.getName();
if (name != null) {
name = name.toLowerCase();
for (final String n : names) {
if (n != null && name.contains(n.toLowerCase())) {
return item;
}
}
}
}
return null;
}
/**
* Gets inventory item at specified index.
*
* @param index The index of inventory item.
* @return The item, or <tt>null</tt> if not found.
*/
public RSItem getItemAt(final int index) {
final RSComponent comp = getInterface().getComponent(index);
return 0 <= index && index < 28 && comp != null ? new RSItem(methods,
comp) : null;
}
/**
* Gets the ID of an item in the inventory with a given name.
*
* @param name The name of the item you wish to find.
* @return The ID of the item or -1 if not in inventory.
*/
public int getItemID(final String name) {
final RSItem item = getItem(name);
return item != null ? item.getID() : -1;
}
/**
* Gets all the items in the inventory.
*
* @return <tt>RSItem</tt> array of the current inventory items or an
* empty <tt>RSItem[]</tt> if unavailable.
*/
public RSItem[] getItems() {
return getItems(false);
}
/**
* Gets all the items in the inventory.
*
* @param cached If the inventory interface should be updated before
* returning the items.
* @return <tt>RSItem</tt> array of the current inventory items or an
* empty <tt>RSItem[]</tt> if unavailable.
*/
public RSItem[] getItems(final boolean cached) {
final RSComponent invIface = getInterface(cached);
if (invIface != null) {
final RSComponent[] comps = invIface.getComponents();
if (comps.length > 0) {
int len = 0;
for (final RSComponent com : comps) {
if (com.getType() == 5) {
++len;
}
}
final RSItem[] inv = new RSItem[len];
for (int i = 0; i < len; ++i) {
final RSComponent item = comps[i];
final int idx = item.getComponentIndex();
if (idx >= 0) {
inv[idx] = new RSItem(methods, item);
} else {
return new RSItem[0];
}
}
return inv;
}
}
return new RSItem[0];
}
/**
* Gets all the items in the inventory matching any of the provided IDs.
*
* @param ids Valid IDs.
* @return <tt>RSItem</tt> array of the matching inventory items.
*/
public RSItem[] getItems(final int... ids) {
final LinkedList<RSItem> items = new LinkedList<RSItem>();
for (final RSItem item : getItems()) {
for (final int i : ids) {
if (item.getID() == i) {
items.add(item);
break;
}
}
}
return items.toArray(new RSItem[items.size()]);
}
/**
* Gets the inventory interface.
*
* @return the current inventory interface if available; otherwise null.
*/
public RSComponent getInterface() {
return getInterface(false);
}
/**
* Gets the inventory interface.
*
* @param cached <tt>true</tt> to skip updating the inventory interface.
* @return the current inventory interface if available; otherwise null.
*/
public RSComponent getInterface(final boolean cached) {
if (methods.interfaces.get(INTERFACE_INVENTORY_BANK).isValid()) {
final RSComponent bankInv = methods.interfaces.getComponent(
INTERFACE_INVENTORY_BANK, 0);
if (bankInv != null && bankInv.getAbsoluteX() > 50) {
return bankInv;
}
}
if (methods.interfaces.get(INTERFACE_INVENTORY_DEPOSIT_BOX).isValid()) {
final RSComponent bankInv = methods.interfaces.getComponent(
INTERFACE_INVENTORY_DEPOSIT_BOX, 17);
if (bankInv != null && bankInv.getAbsoluteX() > 50) {
return bankInv;
}
}
if (methods.interfaces.get(INTERFACE_INVENTORY_SHOP).isValid()) {
final RSComponent shopInv = methods.interfaces.getComponent(
INTERFACE_INVENTORY_SHOP, 0);
if (shopInv != null && shopInv.getAbsoluteX() > 50) {
return shopInv;
}
}
if (methods.interfaces.get(INTERFACE_INVENTORY_PRICE_CHECK).isValid()) {
final RSComponent priceInv = methods.interfaces.getComponent(INTERFACE_INVENTORY_PRICE_CHECK, 0);
if (priceInv != null && priceInv.getAbsoluteX() > 50) {
return priceInv;
}
}
if (methods.interfaces.get(INTERFACE_INVENTORY_EQUIPMENT_BONUSES).isValid()) {
final RSComponent equipInv = methods.interfaces.getComponent(INTERFACE_INVENTORY_EQUIPMENT_BONUSES, 0);
if (equipInv != null && equipInv.getAbsoluteX() > 50) {
return equipInv;
}
}
if (methods.interfaces.get(INTERFACE_INVENTORY_DUNGEONEERING_SHOP).isValid()) {
final RSComponent dungInv = methods.interfaces.getComponent(INTERFACE_INVENTORY_DUNGEONEERING_SHOP, 0);
if (dungInv != null && dungInv.getAbsoluteX() > 50) {
return dungInv;
}
}
if (!cached && methods.game.getTab() != Game.Tab.INVENTORY) {
methods.game.openTab(Game.Tab.INVENTORY);
sleep(random(200, 400));
}
return methods.interfaces.getComponent(INTERFACE_INVENTORY, 0);
}
/**
* Gets the selected inventory item.
*
* @return The current selected item, or <tt>null</tt> if none is selected.
*/
public RSItem getSelectedItem() {
final int index = getSelectedItemIndex();
return index == -1 ? null : getItemAt(index);
}
/**
* Gets the selected item index.
*
* @return The index of current selected item, or -1 if none is selected.
*/
public int getSelectedItemIndex() {
final RSComponent[] comps = getInterface().getComponents();
for (int i = 0; i < Math.min(28, comps.length); ++i) {
if (comps[i].getBorderThickness() == 2) {
return i;
}
}
return -1;
}
/**
* Gets the selected item name.
*
* @return The name of the current selected item, or null if none is
* selected.
*/
public String getSelectedItemName() {
final String name = methods.client.getSelectedItemName();
return name == null ? null : name.replaceAll("<[\\w\\d]+=[\\w\\d]+>", "");
}
/**
* Checks whether or not your inventory is full.
*
* @return <tt>true</tt> if your inventory contains 28 items; otherwise
* <tt>false</tt>.
*/
public boolean isFull() {
return getCount(false) == 28;
}
/**
* Checks whether or not an inventory item is selected.
*
* @return <tt>true</tt> if an item in your inventory is selected; otherwise
* <tt>false</tt>.
*/
public boolean isItemSelected() {
return getSelectedItemIndex() != -1;
}
/**
* Randomizes a point.
*
* @param inventoryPoint The inventory point to be randomized.
* @return A randomized <tt>Point</tt> from the center of the given
* <tt>Point</tt>.
*/
public Point randomizeItemPoint(final Point inventoryPoint) {
return new Point(inventoryPoint.x + random(-10, 10), inventoryPoint.y + random(-10, 10));
}
/**
* Selects the first item in the inventory with the provided ID.
*
* @param itemID The ID of the item to select.
* @return <tt>true</tt> if the item was selected; otherwise <tt>false</tt>.
*/
public boolean selectItem(final int itemID) {
final RSItem item = getItem(itemID);
return item != null && selectItem(item);
}
/**
* Selects the specified item in the inventory
*
* @param item The item to select.
* @return <tt>true</tt> if the item was selected; otherwise <tt>false</tt>.
*/
public boolean selectItem(final RSItem item) {
final int itemID = item.getID();
RSItem selItem = getSelectedItem();
if (selItem != null && selItem.getID() == itemID) {
return true;
}
if (selItem != null) {
selItem.interact("Use");
}
if (!item.interact("Use")) {
return false;
}
for (int c = 0; c < 5 && (selItem = getSelectedItem()) == null; c++) {
sleep(random(200, 300));
}
return selItem != null && selItem.getID() == itemID;
}
/**
* Uses two items together.
*
* @param itemID The first item ID to use.
* @param targetID The item ID you want the first parameter to be used on.
* @return <tt>true</tt> if the first item has been "used" on the other;
* otherwise <tt>false</tt>.
*/
public boolean useItem(final int itemID, final int targetID) {
final RSItem item = getItem(itemID);
final RSItem target = getItem(targetID);
return item != null && target != null && useItem(item, target);
}
/**
* Uses an item on an object.
*
* @param itemID The item ID to use on the object.
* @param object The RSObject you want the item to be used on.
* @return <tt>true</tt> if the "use" action had been used on both the
* RSItem and RSObject; otherwise <tt>false</tt>.
*/
public boolean useItem(final int itemID, final RSObject object) {
final RSItem item = getItem(itemID);
return item != null && useItem(item, object);
}
/**
* Uses two items together.
*
* @param item The item to use on another item.
* @param targetItem The item you want the first parameter to be used on.
* @return <tt>true</tt> if the "use" action had been used on both items;
* otherwise <tt>false</tt>.
*/
public boolean useItem(final RSItem item, final RSItem targetItem) {
methods.game.openTab(Game.Tab.INVENTORY);
return selectItem(item) && targetItem.interact("Use");
}
/**
* Uses an item on an object.
*
* @param item The item to use on another item.
* @param targetObject The RSObject you want the first parameter to be used on.
* @return <tt>true</tt> if the "use" action had been used on both the
* RSItem and RSObject; otherwise <tt>false</tt>.
*/
public boolean useItem(final RSItem item, final RSObject targetObject) {
methods.game.openTab(Game.Tab.INVENTORY);
return selectItem(item) && targetObject.interact("Use", targetObject.getName());
}
}