Jump to content

Recommended Posts

Post rewritten after rewritting and updating the code multiple times.

So I decided to give writing my own GE API a go and this is what I've come up with so far, using Exchange#offer(name, price, quantity, buy) will do the following:

  1. If the GE is closed, it will open it and continue making the offer.
  2. If the price is set to -1 then it will use the buttons to increase or decrease the price, depending on whether it is a buy or sell offer, until it is at a price that will buy/sell instantly. Otherwise it will use the custom input button to set the price.
  3. It will set the quantity using the 1/10/100/1000 buttons. I plan on updating this to randomise between using them and the custom input method shortly. Edit* I hadn't even remembered implementing this until I saw it do it whilst testing the method, and it was beautiful, but if it goes over the buy quantity accidently, in the example I saw it was clicking +100 and clicked it again too fast so instead of stopping before its target of 875 it got to 900, it will then use the custom amount interface to input 875, beautiful.
  4. It will prioritise buy offers over sell offers so that if there isn't an empty slot available, or any items to collect, then it will cancel a sell offer, collect it and continue now it has a free slot.
  5. If there isn't a free slot available and we are trying to sell something it will return true, this is so that in my scripts it will remove the item from a toSell HashMap and put it back into the bank to sell later because it has bought the items it needs to continue botting. If it is instead trying to buy something and there are no empty slots or sell offers to cancel then it will wait for something to buy and continue once it can collect something and therefore has an empty slot.
  6. Update* It will now search for the item 1-3 words at a time checking the first 9 results each time and will choose the item as soon as it is visible as a human would. I might update this so that it randomises more, sometimes entering the whole first word of an items name straight away, because I sometimes do that, most of the time though I enter as few characters as I need to, I think, thoughts?

Let me know what you think, the code is probably disgusting to look at for some of you but for others just starting out like me it could be a valuable learning tool, for how not to code ;) All feedback and constructive criticism appreciated.

Exchange Class

Spoiler
package scripts.api.utils.grandexchange;

import org.tribot.api.Clicking;
import org.tribot.api.General;
import org.tribot.api.Timing;
import org.tribot.api.input.Keyboard;
import org.tribot.api2007.Interfaces;
import org.tribot.api2007.Inventory;
import org.tribot.api2007.NPCs;
import org.tribot.api2007.types.RSInterface;
import org.tribot.api2007.types.RSItem;
import org.tribot.api2007.types.RSNPC;

import scripts.api.data.GEInterfaces;
import scripts.api.utils.conditions.GEConditions;
import scripts.api.utils.helpers.InfoHelper;

public class Exchange {
	
	public static boolean offer(int itemID, int price, int quantity, boolean buy) {
		String name = InfoHelper.getItemNameFromID(itemID);
		if(name == null) return false;
		
		switch(getOfferState(itemID, price, quantity, buy)) {
		case GE_CLOSED:
			open();
			General.sleep(250,400);
			break;
		case HISTORY_SCREEN:
			exitHistoryScreen();
			General.sleep(250,400);
			break;
		case LOADING_SCREENS:
			General.sleep(300,600);
			break;
		case OFFER_SCREEN_ITEM_WRONG:
			handleWrongOfferItem(name, itemID, buy);
			General.sleep(250,400);
			break;
		case OFFER_SCREEN_OFFER_CORRECT:
			if(GEInterfaces.CONFIRM_NEW_OFFER.get().click())
				Timing.waitCondition(GEConditions.GESelectionWindowVisible(), General.random(4000, 7000));
			General.sleep(250,400);
			break;
		case OFFER_SCREEN_PRICE_WRONG:
			handleWrongOfferPrice(price, buy);
			General.sleep(600, 900);
			break;
		case OFFER_SCREEN_QUANTITY_WRONG:
			handleWrongOfferQuantity(quantity);
			General.sleep(150, 300);
			break;
		case OFFER_SCREEN_TYPE_WRONG:
			if(GEInterfaces.BACK_BTN.get().click())
				Timing.waitCondition(GEConditions.GESelectionWindowVisible(), General.random(4000, 7000));
			General.sleep(250,400);
			break;
		case SELECTION_SCREEN_CAN_COLLECT:
			if(GEInterfaces.COLLECT_BTN.get().click())
				Timing.waitCondition(GEConditions.hasCollected(), General.random(4000, 7000));
			General.sleep(250,400);
			break;
		case SELECTION_SCREEN_CAN_MAKE_OFFER:
			handleMakingOffer(name, buy);
			General.sleep(600,1200);
			break;
		case SELECTION_SCREEN_OFFER_ACTIVE:
			return true;
		case SELECTION_SCREEN_SHOULD_CANCEL_OFFER:
			handleCancellingOffer();
			General.sleep(400,700);
			break;
		case SELECTION_SCREEN_SHOULD_RETURN_TRUE:
			return true;
		case SELECTION_SCREEN_SHOULD_WAIT:
			General.sleep(3000, 6000);
			break;
		}
		
		return offer(itemID, price, quantity, buy);
	}
	
	public static OfferState getOfferState(int itemID, int price, int quantity, boolean buy) {
		if(isOpen()) {
			//The GE is open, what window are we on?
			if(GEInterfaces.SELECTION_WINDOW.isVisible()) {
				//We are on the selection window.
				for(int i = 7; i < 15 ; i++) {
					//Do we already have an offer of this item?
					RSInterface item = Interfaces.get(465, i, 18);
					if(item != null && !item.isHidden()) {
						if(item.getComponentItem() == itemID) {
							//Yes we do, is it the right type?
							RSInterface type = Interfaces.get(465, i, 16);
							if(type != null && !type.isHidden()) {
								if(type.getText().contains("Buy")) {
									if(buy == true) {
										//Yes it is, return we have made the offer.
										return OfferState.SELECTION_SCREEN_OFFER_ACTIVE;
									}
								} else {
									if(buy == false) {
										//Yes it is, return we have made the offer.
										return OfferState.SELECTION_SCREEN_OFFER_ACTIVE;
									}
								}
							}
						}
					}
				}	
				//No we don't already have an active offer
				for(int b = 7; b < 15 ; b++) {
					//Do we have an empty offer slot?
					RSInterface type = Interfaces.get(465, b, 16);
					if(type != null && !type.isHidden()) {
						if(type.getText().contains("Empty")) {
							//Yes we do, return we can make the offer
							return OfferState.SELECTION_SCREEN_CAN_MAKE_OFFER;
						}
					}
				}
				//No we don't, do we have any offers to collect?
				if(GEInterfaces.COLLECT_BTN.isVisible()) {
					//Yes we do, return we can collect offers
					return OfferState.SELECTION_SCREEN_CAN_COLLECT;
				}
						
				//No we don't, should we cancel an offer?
				if(buy == true) {
					//Check if there is a sell offer to cancel
					for(int c = 7; c < 15 ; c++) {
						RSInterface type = Interfaces.get(465, c, 16);
						if(type != null && !type.isHidden()) {
							if(type.getText().contains("Sell")) {
								//Yes there is, return we can abort a sell offer.
								return OfferState.SELECTION_SCREEN_SHOULD_CANCEL_OFFER;
							}
						}
					}
					
					//No there isn't, we should wait because we are trying to buy something
					return OfferState.SELECTION_SCREEN_SHOULD_WAIT;
				} else {
					return OfferState.SELECTION_SCREEN_SHOULD_RETURN_TRUE;
				}
			} else if(GEInterfaces.CONFIRM_NEW_OFFER.isVisible()) {
				//We are on an offer screen, check that it is the right type
				if(GEInterfaces.BUY_WINDOW.isVisible())
					if(buy == false)
						return OfferState.OFFER_SCREEN_TYPE_WRONG;
				
				if(GEInterfaces.SELL_WINDOW.isVisible())
					if(buy == true)
						return OfferState.OFFER_SCREEN_TYPE_WRONG;
				
				//The type is correct, check if the item is correct
				if(GEInterfaces.OFFER_ITEM.get().getComponentItem() == itemID) {
					//The item is correct, check if the price is correct
					int currentPrice = InfoHelper.stringToInt(GEInterfaces.OFFER_PRICE.get().getText(), " coins",",");
					if(price == -1) {
						int avrPrice = InfoHelper.stringToInt(GEInterfaces.OFFER_AVR_PRICE.get().getText(), ",");
						if(buy == true) {
							Double targ = avrPrice * 1.2;
							int target = targ.intValue();
							if(currentPrice > target) {
								//The price is correct, check if the quantity is correct
								int currentQuantity = InfoHelper.stringToInt(GEInterfaces.OFFER_QUANTITY.get().getText(), ",");
								if(currentQuantity == quantity) {
									//The quantity is correct, return confirm offer
									return OfferState.OFFER_SCREEN_OFFER_CORRECT;
								} else {
									//No the quantity isn't correct, return quantity wrong
									return OfferState.OFFER_SCREEN_QUANTITY_WRONG;
								}
							} else {
								//the price is wrong
								return OfferState.OFFER_SCREEN_PRICE_WRONG;
							}
						} else {
							Double targ = avrPrice * 0.67;
							int target = targ.intValue();
							if(currentPrice < target) {
								//The price is correct, check if the quantity is correct
								int currentQuantity = InfoHelper.stringToInt(GEInterfaces.OFFER_QUANTITY.get().getText(), ",");
								if(currentQuantity == quantity) {
									//The quantity is correct, return confirm offer
									return OfferState.OFFER_SCREEN_OFFER_CORRECT;
								} else {
									//No the quantity isn't correct, return quantity wrong
									return OfferState.OFFER_SCREEN_QUANTITY_WRONG;
								}
							} else {
								//the price is wrong
								return OfferState.OFFER_SCREEN_PRICE_WRONG;
							}
						}
					} else if(currentPrice == price) {
						//The price is correct, check if the quantity is correct
						int currentQuantity = InfoHelper.stringToInt(GEInterfaces.OFFER_QUANTITY.get().getText(), ",");
						if(currentQuantity == quantity) {
							//The quantity is correct, return confirm offer
							return OfferState.OFFER_SCREEN_OFFER_CORRECT;
						} else {
							//No the quantity isn't correct, return quantity wrong
							return OfferState.OFFER_SCREEN_QUANTITY_WRONG;
						}
					} else {
						//No the price isn't correct, return price wrong
						return OfferState.OFFER_SCREEN_PRICE_WRONG;
					}
				} else {
					//The item isn't correct
					return OfferState.OFFER_SCREEN_ITEM_WRONG;
				}
			} else if(GEInterfaces.HISTORY_WINDOW.isVisible()){
				//We are on the history screen, return on history screen
				return OfferState.HISTORY_SCREEN;
			} else {
				return OfferState.LOADING_SCREENS;
			}
		} else {
			return OfferState.GE_CLOSED;
		}
	}
	
	public static enum QuantityState {
		PLUS_1000, PLUS_100, PLUS_10, PLUS_1, CUSTOM, PLUS, MINUS, CORRECT
	}

	public static QuantityState getQuantityState(int goal, int current) {
		if(goal == current)
			return QuantityState.CORRECT;
		if(goal > current + 998)
			return QuantityState.PLUS_1000;
		if(goal > current + 98)
			return QuantityState.PLUS_100;
		if(goal > current + 9)
			return QuantityState.PLUS_10;
		if(goal > current)
			return General.random(1, 10) > 2 ? QuantityState.PLUS_1 : QuantityState.PLUS;
		if(goal + 10 < current)
			return QuantityState.CUSTOM;
		return QuantityState.MINUS;
	}
	
	public enum OfferState {
		 GE_CLOSED,
		 SELECTION_SCREEN_OFFER_ACTIVE,
		 SELECTION_SCREEN_CAN_MAKE_OFFER,
		 SELECTION_SCREEN_CAN_COLLECT,
		 SELECTION_SCREEN_SHOULD_RETURN_TRUE,
		 SELECTION_SCREEN_SHOULD_CANCEL_OFFER,
		 SELECTION_SCREEN_SHOULD_WAIT,
		 OFFER_SCREEN_TYPE_WRONG,
		 OFFER_SCREEN_ITEM_WRONG,
		 OFFER_SCREEN_PRICE_WRONG,
		 OFFER_SCREEN_QUANTITY_WRONG,
		 OFFER_SCREEN_OFFER_CORRECT,
		 HISTORY_SCREEN,
		 LOADING_SCREENS
	}
	
	public enum WindowState {
		CLOSED, SELECTION_SCREEN, BUY_SCREEN, SELL_SCREEN, HISTORY_SCREEN
	}
	
	public static WindowState getWindowState() {
		if(GEInterfaces.SELECTION_WINDOW.isVisible())
			return WindowState.SELECTION_SCREEN;
		
		if(GEInterfaces.HISTORY_WINDOW.isVisible())
			return WindowState.HISTORY_SCREEN;
		
		if(GEInterfaces.BUY_WINDOW.isVisible())
			return WindowState.BUY_SCREEN;
		
		if(GEInterfaces.SELL_WINDOW.isVisible())
			return WindowState.SELL_SCREEN;
		
		return WindowState.CLOSED;
	}
	
	public static void handleCancellingOffer() {
		for(int i = 7; i < 15 ; i++) {
			RSInterface type = Interfaces.get(465, i, 16);
			if(type != null && !type.isHidden()) {
				if(type.getText().contains("Sell")) {
					RSInterface slot = Interfaces.get(465, i, 2);
					if(slot != null && !slot.isHidden()) {
						if(slot.click("Abort offer")) {
							Timing.waitCondition(GEConditions.canCollect(), General.random(4000, 7000));
						}
					}
				}
			}
		}
	}
	
	public static void handleMakingOffer(String name, boolean buy) {
		if(buy == true) {
			for(int i = 7; i < 15 ; i++) {
				RSInterface type = Interfaces.get(465, i, 16);
				if(type != null && !type.isHidden()) {
					if(type.getText().contains("Empty")) {
						RSInterface buyBtn = Interfaces.get(465, i, 3);
						if(buyBtn != null && !buyBtn.isHidden()) {
							if(buyBtn.click()) {
								Timing.waitCondition(GEConditions.GEBuyWindowVisible(), General.random(4000, 7000));
							}
						}
					}
				}
			}
		} else {
			RSItem[] target = Inventory.find(name);
			if(target != null && target.length > 0) {
				if(target[0].click()) {
					Timing.waitCondition(GEConditions.GESellWindowVisible(), General.random(4000, 7000));
				}
			}
		}
	}
	
	public static void handleWrongOfferPrice(int price, boolean buy) {
		if(GEInterfaces.OFFER_AVR_PRICE.isVisible()) {
			if(price == -1) {
				if(buy == true) {
					GEInterfaces.PRICE_PLUS_5.get().click();
					return;
				} else {
					GEInterfaces.PRICE_MINUS_5.get().click();
					return;
				}
			}
		}
		
		if(GEInterfaces.SEARCH_ITEM_INPUT_TEXT.isVisible()) {
			Keyboard.typeSend(Integer.toString(price));
			Timing.waitCondition(GEConditions.GESearchBoxDissapeared(), General.random(4000, 7000));
			return;
		} 
		
		if(GEInterfaces.PRICE_CUSTOM.isVisible()) {
			if(GEInterfaces.PRICE_CUSTOM.get().click()) {
				Timing.waitCondition(GEConditions.GESearchBoxAppeared(), General.random(4000, 7000));
				return;
			}
		}
	}
	
	public static void handleWrongOfferQuantity(int quantity) {
		// quantity isn't correct
		if(GEInterfaces.SEARCH_ITEM_INPUT_TEXT.isVisible()) {
			Keyboard.typeSend(Integer.toString(quantity));
			Timing.waitCondition(GEConditions.GESearchBoxDissapeared(), General.random(4000, 7000));
			return;
		} 
		int currentQuantity = InfoHelper.stringToInt(GEInterfaces.OFFER_QUANTITY.get().getText(), ",");
		switch(getQuantityState(quantity, currentQuantity)) {
		case CORRECT:
			break;
		case CUSTOM:
			if(GEInterfaces.QUAN_CUSTOM.isVisible()) {
				GEInterfaces.QUAN_CUSTOM.get().click();
				Timing.waitCondition(GEConditions.GESearchBoxAppeared(), General.random(4000, 7000));
			}
			break;
		case MINUS:
			if(GEInterfaces.QUAN_MINUS.isVisible())
				GEInterfaces.QUAN_MINUS.get().click();
			break;
		case PLUS:
			if(GEInterfaces.QUAN_PLUS.isVisible())
				GEInterfaces.QUAN_PLUS.get().click();
			break;
		case PLUS_1:
			if(GEInterfaces.QUAN_PLUS_1.isVisible())
				GEInterfaces.QUAN_PLUS_1.get().click();
			break;
		case PLUS_10:
			if(GEInterfaces.QUAN_PLUS_10.isVisible())
				GEInterfaces.QUAN_PLUS_10.get().click();
			break;
		case PLUS_100:
			if(GEInterfaces.QUAN_PLUS_100.isVisible())
				GEInterfaces.QUAN_PLUS_100.get().click();
			break;
		case PLUS_1000:
			if(GEInterfaces.QUAN_PLUS_1000.isVisible())
				GEInterfaces.QUAN_PLUS_1000.get().click();
			break;
		}
	}
	
	public static void handleWrongOfferItem(String name, int itemID, boolean buy) {
		if(buy == true) {
			if(GEInterfaces.SEARCH_ITEM_INPUT_TEXT.isVisible()) {
				if(GEInterfaces.SEARCH_ITEM_RESULTS_CONTAINER.isVisible()) {
					if(hasSearchTarget(itemID)) {
						if(clickSearchTarget(itemID)) {
							General.sleep(1300, 2100);
							return;
						}
					} else {
						String alreadyTyped = GEInterfaces.SEARCH_ITEM_INPUT_TEXT.get().getText();
						String trimmed = alreadyTyped.substring(46, alreadyTyped.length()-1);
						Keyboard.typeString(InfoHelper.partNameToType(name, trimmed.replace("*", "")));
						General.sleep(600,900);
						return;
					}
					
				}
			}
			
			if(GEInterfaces.OFFER_ITEM.isVisible()) {
				if(GEInterfaces.OFFER_ITEM.get().click()) {
					Timing.waitCondition(GEConditions.GESearchBoxAppeared(), General.random(4000, 7000));
					return;
				}
			}
		} else {
			RSItem[] target = Inventory.find(itemID);
			if(target != null && target.length < 0) {
				if(target[0].click()) {
					General.sleep(900, 2100);
				}
			}
		}
	}
	
	public static boolean hasSearchTarget(int itemID) {
		if(GEInterfaces.SEARCH_RESULT_1.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_1.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_2.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_2.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_3.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_3.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_4.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_4.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_5.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_5.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_6.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_6.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_7.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_7.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_8.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_8.get().getComponentItem() == itemID) {
				return true;
			}
		}
		if(GEInterfaces.SEARCH_RESULT_9.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_9.get().getComponentItem() == itemID) {
				return true;
			}
		}
		return false;
	}
	
	public static boolean clickSearchTarget(int itemID) {
		if(GEInterfaces.SEARCH_RESULT_1.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_1.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_1.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_2.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_2.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_2.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_3.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_3.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_3.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_4.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_4.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_4.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_5.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_5.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_5.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_6.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_6.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_6.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_7.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_7.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_7.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_8.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_8.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_8.get().click();
			}
		}
		if(GEInterfaces.SEARCH_RESULT_9.isVisible()) {
			if(GEInterfaces.SEARCH_RESULT_9.get().getComponentItem() == itemID) {
				return GEInterfaces.SEARCH_RESULT_9.get().click();
			}
		}
		return false;
	}
	
	public static void exitHistoryScreen() {
		if(GEInterfaces.EXCHANGE_BTN.isVisible()) {
			if(GEInterfaces.EXCHANGE_BTN.get().click()) {
				Timing.waitCondition(GEConditions.GESelectionWindowVisible(), General.random(4000, 7000));
			}
		}
	}
	
	public static boolean isOpen() {
		return GEInterfaces.MASTER.isVisible() || GEInterfaces.HISTORY_WINDOW.isVisible();
	}
	
	public static boolean open() {
		if(isOpen()) return true;
		
		RSNPC[] geClerks = NPCs.findNearest("Grand Exchange Clerk");
		if (geClerks.length > 0)
			if(Clicking.click("Exchange Grand Exchange Clerk", geClerks[0])) 
				Timing.waitCondition(GEConditions.GEOpen(), General.random(3000, 7000));
				return isOpen();
	}

}

 

GEInterfaces Class

Spoiler
package scripts.api.data;

import org.tribot.api2007.Interfaces;
import org.tribot.api2007.types.RSInterface;

public enum GEInterfaces {

	MASTER(465), SELECTION_WINDOW(465, 7, 16), HISTORY_WINDOW(383, 3, 0), BUY_WINDOW(465, 24, 19, 1118), SELL_WINDOW(465, 24, 19, 1119),
	
	SLOT(465, 7), SLOT_ACTIVE(465, 7, 2), SLOT_TYPE(465, 7, 16), SLOT_ITEM(465, 7, 18), SLOT_NAME(465, 7, 19), 
	SLOT_PROGRESS_WIDTH(465, 7, 22), SLOT_PRICE(465, 7, 25), SLOT_BUY_BTN(465, 7, 3), SLOT_SELL_BTN(465, 7, 4),
	
	SEARCH_ITEM_RESULTS_CONTAINER(162, 46), SEARCH_ITEM_INPUT_TEXT(162, 38),
	SEARCH_RESULT_1(162, 46, 2), SEARCH_RESULT_2(162, 46, 5), SEARCH_RESULT_3(162, 46, 8), SEARCH_RESULT_4(162, 46, 11), SEARCH_RESULT_5(162, 46, 14),
	
	OFFER_NAME(465, 24, 25), OFFER_ITEM(465, 24, 21), OFFER_PRICE(465, 24, 39), OFFER_QUANTITY(465, 24, 32), OFFER_TOTAL(465, 24, 43),
	
	QUAN_MINUS(465, 24, 1), QUAN_PLUS(465, 24, 2), QUAN_PLUS_1(465, 24, 3), QUAN_PLUS_10(465, 24, 4), QUAN_PLUS_100(465, 24, 5),
	QUAN_PLUS_1000(465, 24, 6), QUAN_CUSTOM(465, 24, 7),
	
	PRICE_MINUS(465, 24, 8), PRICE_PLUS(465, 24, 9), PRICE_MINUS_5(465, 24, 10), PRICE_CUSTOM(465, 24, 12), PRICE_PLUS_5(465, 24, 13),
	
	CONFIRM_NEW_OFFER(465, 27), 
	
	HISTORY_BTN(465, 3), EXCHANGE_BTN(383,2), COLLECT_BTN(465, 6, 0),
	
	CLOSE_OFFER(465, 2, 11), CLOSE_HISTORY(383, 1, 11), BACK_BTN(465, 4);
	
	
	private int parent, child, component, texture;
	private int[] id;
	
	GEInterfaces(int... ids){
		this.id = ids;
		switch(id.length) {
		case 1:
			this.parent = id[0];
			break;
		case 2:
			this.parent = id[0];
			this.child = id[1];
			break;
		case 3:
			this.parent = id[0];
			this.child = id[1];
			this.component = id[2];
			break;
		case 4:
			this.parent = id[0];
			this.child = id[1];
			this.component = id[2];
			this.texture = id[3];
		}
	}
	
	public boolean isVisible() {
		switch(id.length) {
		case 1:
			return Interfaces.get(parent) != null && !Interfaces.get(parent).isHidden();
		case 2:
			return Interfaces.get(parent, child) != null && !Interfaces.get(parent, child).isHidden();
		case 3:
			return Interfaces.get(parent, child, component) != null && !Interfaces.get(parent, child, component).isHidden();
		case 4:
			return Interfaces.get(parent, child, component) != null && !Interfaces.get(parent, child, component).isHidden() && Interfaces.get(parent, child, component).getTextureID() == texture;
		}
			
		return false;
	}
	
	public int[] getID() {
		switch(id.length) {
		case 1:
			return new int[] {parent};
		case 2:
			return new int[] {parent, child};
		}
		return new int[] {parent, child, component};
	}
	
	public RSInterface get() {
		switch(id.length) {
		case 1:
			return Interfaces.get(parent);
			
		case 2:
			return Interfaces.get(parent, child);
		}
		return Interfaces.get(parent, child, component);
	}
}

 

GEConditions Class

Spoiler
package scripts.api.utils.conditions;

import scripts.api.data.GEInterfaces;
import scripts.api.utils.grandexchange.Exchange;

public class GEConditions {

	public static Condition hasCollected() {
		return new Condition(() -> !GEInterfaces.COLLECT_BTN.isVisible());
	}
	
	public static Condition canCollect() {
		return new Condition(() -> GEInterfaces.COLLECT_BTN.isVisible());
	}
	
	public static Condition GEOpen() {
		return new Condition(() -> Exchange.isOpen());
	}
	
	public static Condition GEClosed() {
		return new Condition(() -> !Exchange.isOpen());
	}
	
	public static Condition GEBuyWindowVisible() {
		return new Condition(() -> GEInterfaces.BUY_WINDOW.isVisible());
	}
	
	public static Condition GESellWindowVisible() {
		return new Condition(() -> GEInterfaces.SELL_WINDOW.isVisible());
	}
	
	public static Condition GESelectionWindowVisible() {
		return new Condition(() -> GEInterfaces.SELECTION_WINDOW.isVisible());
	}
	
	public static Condition GESearchBoxDissapeared() {
		return new Condition(() -> !GEInterfaces.SEARCH_ITEM_INPUT_TEXT.isVisible());
	}
	
	public static Condition GESearchBoxAppeared() {
		return new Condition(() -> GEInterfaces.SEARCH_ITEM_INPUT_TEXT.isVisible());
	}
	
	private interface BooleanLambda{
        boolean active();
    }

    private static class Condition extends org.tribot.api.types.generic.Condition{
        private BooleanLambda lambda;

        public Condition(BooleanLambda lambda){
            super();
            this.lambda = lambda;
        }

        @Override
        public boolean active() {
            return lambda.active();
        }
    }
	
}

 

InfoHelper Class

Spoiler
package scripts.api.utils.helpers;

import org.tribot.api.General;
import org.tribot.api2007.types.RSItemDefinition;

public class InfoHelper {

	public static int stringToInt(String input, String... toRemove) {
		String[] forRemoving = toRemove;
		switch(forRemoving.length) {
		case 1:
			return Integer.parseInt(input.replace(forRemoving[0], ""));
		case 2:
			String first = input.replace(forRemoving[0], "");
			return Integer.parseInt(first.replace(forRemoving[1], ""));
		case 3:
			String first2 = input.replace(forRemoving[0], "");
			String second = first2.replace(forRemoving[1], "");
			return Integer.parseInt(second.replace(forRemoving[2], ""));
		default:
			return -1;
		}
	}
	
	public static String partNameToType(String fullName, String alreadyTyped) {
		String remaining = fullName.replaceFirst(alreadyTyped, "");
		return remaining.length() > 2 ? remaining.substring(0, General.random(1, 2)) : remaining;
	}
	
	public static String getItemNameFromID(int itemID){
        RSItemDefinition itemDef  = RSItemDefinition.get(itemID);
        if(itemDef !=null){
            String itemName = itemDef.getName();
            if(itemName!=null){
                return itemName;
            }
        }
        return "";
	}
	
}

 

Thank you to everyone that has read this far, it is appreciated :)

Rewritten, if you have read again, even more appreciation! ;)

Edited by NeuroGenix
Completely rewritten, renamed, added more functions/features, rewrote topic

Share this post


Link to post
Share on other sites

I just realised I should probably null check the getNameFromItemDefinition method in the beginning of the GE#Offer method.

- Also there is a lot of over lapping code between the Buy and Sell Screen - Setting the price, quantity and confirming the offer. This could probably be trimmed down a lot, as the interface ID's are identical in both scenarios; I haven't gotten around to neatening it all up yet but that will be a goal.

Share this post


Link to post
Share on other sites

To determine if an item is "collectable", I'd say it is a better approach to use the RSGEOffer#getAmountTransferred() and compare it to the amount you posted the offer for.

I've noticed things to get way messier when relying on the collection button being visible to determine when to collect items, it makes things harder to track.

 

Also another thing, make your logic less restricted.

You're example:

If we have no free slot -> if we have nothing to collect -> if we are trying to buy something and there is a sell offer it will cancel it -> if we are trying to sell something it will return true 

 

A less restricted approach could be anything, here's a crappy example:

public static EXAMPLE_ENUM_STATE getState() {

    if (forAllOffers_If_AmountTransferred_IsEqualTo_AmountOffered_Or_isEqualTo_AmountTransferredToCollect_Threshold()) {

        return COLLECTIONS_PENDING;

    }

    If (getEmptySlots() > 0) {

        if (weHave_EnoughItems_ToSell() && weStill_WantToSell())

            return SELL_ITEMS;

        if ( weHave_Not-EnoughItems_WeWant() && weHave_EnoughCoins_ToBuy_whatWeWant())

            return BUY_ITEMS;

    }

    return NOTHING_TO_DO;

}

 

Edited by JoeDezzy1
  • Thanks 1

Share this post


Link to post
Share on other sites

Also yes, always null check. Read the API docs if you're unsure what a method can return to see if you need to null check.

 

Most getters in the API should be null checked (After it is stored into a variable), and mostly everything except a few things which return an array, should be bounds checked as array.length > 0 (After it is stored into a variable)

Share this post


Link to post
Share on other sites
1 minute ago, IceKontroI said:

@NeuroGenix I'm not sure if you just wanted your own implementation of this, but Tribot already does have all the GE constants set up (not sure if they dynamically change with updates).

And Yes, I've just pushed an update addressing issues that were previously posted, it is not live yet but it should be soon.

Although I give him props for doing it himself, I did so as well a while ago :D

Turned out to be a good thing!

Share this post


Link to post
Share on other sites
1 hour ago, JoeDezzy1 said:

To determine if an item is "collectable", I'd say it is a better approach to use the RSGEOffer#getAmountTransferred() and compare it to the amount you posted the offer for.

I've noticed things to get way messier when relying on the collection button being visible to determine when to collect items, it makes things harder to track.

 

Also another thing, make your logic less restricted.

You're example:

If we have no free slot -> if we have nothing to collect -> if we are trying to buy something and there is a sell offer it will cancel it -> if we are trying to sell something it will return true 

 

A less restricted approach could be anything, here's a crappy example:

public static EXAMPLE_ENUM_STATE getState() {

    if (forAllOffers_If_AmountTransferred_IsEqualTo_AmountOffered_Or_isEqualTo_AmountTransferredToCollect_Threshold()) {

        return COLLECTIONS_PENDING;

    }

    If (getEmptySlots() > 0) {

        if (weHave_EnoughItems_ToSell() && weStill_WantToSell())

            return SELL_ITEMS;

        if ( weHave_Not-EnoughItems_WeWant() && weHave_EnoughCoins_ToBuy_whatWeWant())

            return BUY_ITEMS;

    }

    return NOTHING_TO_DO;

}

 

Thank you, I'll keep you suggestion in mind if I run into any problems with detecting when items are collectable, right now it seems to be working well - Unless it remove sleeps and it changes states before the interface has loaded, I imagine that would be an issue with your suggestion as well though?

That is a good idea about making my script more flexible, I am actually rewritting it all right now and had already began implementing a similar idea (I think). I'll edit my post in an hour or so when it's finished and tested and it'd be helpful to know if it's what you mean.

1 hour ago, IceKontroI said:

@NeuroGenix I'm not sure if you just wanted your own implementation of this, but Tribot already does have all the GE constants set up (not sure if they dynamically change with updates).

I wanted my own class so I could update it and not have to rely on the Tribot API being up to date. I also feel like it gives me more flexibility, it's really easy to null check and click using that GEInterface class I made, I'm not sure if it is that simple when using the Tribot API?

1 hour ago, JoeDezzy1 said:

Also yes, always null check. Read the API docs if you're unsure what a method can return to see if you need to null check.

 

Most getters in the API should be null checked (After it is stored into a variable), and mostly everything except a few things which return an array, should be bounds checked as array.length > 0 (After it is stored into a variable)

I have updated that in the new version, I think I have done it correct but if I haven't can you let me know when I edit this post later please :)

1 hour ago, JoeDezzy1 said:

And Yes, I've just pushed an update addressing issues that were previously posted, it is not live yet but it should be soon.

Although I give him props for doing it himself, I did so as well a while ago :D

Turned out to be a good thing!

Thats good to hear.

Thank you man, I'm sure it'll turn out to be a good thing for me too :)

Share this post


Link to post
Share on other sites

Updated again, it will now use the +/-5% buttons to increase/decrease the price accordingly until it has reached a price in which it will instantly buy/sell if you set the price to -1 in Exchange#offer(int itemID, int price, int quantity, boolean buy).

I'm really chuffed with how it's turned out so far, the only thing I really need to add to it is antiban. I'm not familiar with implementing abc, could someone tell me whether or not I could use the human reaction times for something like this or not? Because if I remember correctly its not to be used in situations where the reaction time is low, and I'm thinking the GE is one of those situations?

Share this post


Link to post
Share on other sites
9 hours ago, NeuroGenix said:

Having an issue with the waitconditions return true too quickly, putting in an additional sleep before it recalled the offer method seems to fix it, but looks more bot like, suggestions?

This is because the logic in your wait conditions doesn't match the logic you are depending on for your actions to execute.

i.e) if (Inventory.find(item).length > 0) waitFor(Inventory.find(item).length == 0);

Share this post


Link to post
Share on other sites
2 hours ago, JoeDezzy1 said:

This is because the logic in your wait conditions doesn't match the logic you are depending on for your actions to execute.

i.e) if (Inventory.find(item).length > 0) waitFor(Inventory.find(item).length == 0);

Can you give me an example from the code I've written where this is the case? So I understand what you mean better.

Share this post


Link to post
Share on other sites

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

  • Similar Content

    • By zoxind
      I've written my first, I would say for now basic script for combat training. 
      One of the main reasons why I chose to use Tribot is because of abc2. But while reading the post on the tutorial on how to implement it in your own code (
      ) I didn't really understand the method(the way) on how to implement it in code. 
      Could anyone please send me a personal message with an explanation on how to implement it correctly, or write a reply here.
      It would be very nice, if you would include an actual code example of it, that would help me to understand it better.
      Thank you in advance.
    • By Artificial
      Summary
      Collects planks that at the barbarian outpost plank spot. Banks the planks once you have a full inventory and hops worlds when all planks on one world have been picked up. Makes up to 200K+ an hour with no requirements needed. Just start the bot at the Barbarian Outpost bank or near the planks.
       
      Implements ABC2 Antiban methods. Supports custom world hopping method Antiban methods based on real life data from human players. Makes 200K+ an hour No requirements or starting cash needed. Features dynamic paint that shows status of script, GP per hour rate, time ran, and planks collected Features GUI  
      Perfect Goldfarming Script
      This script is a perfect script to run on multiple accounts and collect gold. All it requires is for you to start the script at Barbarian outpost. There are no requirements needed or starting cash needed. 

      Contact
      For any support or questions, comment below or email me: [email protected] 
    • By IceKontroI
      [ICE] Market Buddy
      Market Buddy is the ultimate utility script for both manual flippers and users of merching scripts. It's a free and feature rich application designed to provide meaningful feedback to users and botters that flip items on the Grand Exchange. Typically you're only able to run one script at a time on TRiBot, however MB can be run alongside other scripts which makes it compatible with scripts like Tau Grand Exchange. MB doesn't actually perform any actions or antibans in-game so it won't interfere with any script you decide to run with it. This is also the reason this script has a banrate of 0. The only thing to worry about is the banrate of another script you might be running with it and whether or not the TRiBot client is detectable (it's not).
      ATTENTION: Currently the script cannot fetch buy limits from GE-Tracker. Everything else works as intended, and this is the only broken aspect as far as I know right now.
      This will be fixed at some point, but I have a lot on my plate so that could be a while.
      It's free, why not give it a try?

      Features
      Can be run alongside other scripts Simply activate this script first and you'll find you can run another script after User friendly interface to display information Detailed tooltips for each piece of data on display Can be toggled on/off under settings menu Tracks total profit while using the script Profit per hour Total profit Return on investment (in parentheses) Total profit / Total spending Only takes completed offers into account Displays how much profit each item is bringing in Profit / Time spent being traded More intuitive formula than Profit / Script runtime Displays margin as a percentage of average buy price in parentheses Visual breakdown of how your time is being spent on each item Comprehensive breakdown of the item's trade volume statistics Update mode Average amount of progress made on offers Average time it takes to increment progress for an offer Minute view Quantity traded (bought and sold) in one minute Tracks your progress and buy limits Overall mode Total sold / Total bought Buy limit mode Total bought / Item's buy limit  Resets progress every 4 hours Screenshot

      FAQ
      What's the banrate of this script? There is no banrate as it doesn't actually perform any actions in-game. Banrate can come from other sources like client detection and any script you run alongside it. What do you mean you can run this alongside other scripts? Run this script first, then you'll find you can run another script immediately after. Can I turn off those annoying tooltips? Yes, you can do this through the settings menu. Why is my Net Profit (Hourly) not as good as the profit of some of my individual items? This is probably because you made a lot of cash quickly from those items but didn't spend a long time trading them. If you make 1000 GP trading 1000 Nature runes in the span of 30 seconds it's going to be a lot of money during those 30 seconds. But the Net Profit (Hourly) is based on Market Buddy runtime so that 30 seconds will have only a small impact on say 1 hour of MB runtime.
    • By JordiLaFjord
      Hey.
      Just trying to right click make all on the gold bracelet interface. Most recent thing i've trid is getting the RSInterfaceChild braceInterface = Interfaces.get(446,47); then calling it as braceInterface.click("Make-All");
      I've tried a few other things from the forum that I can't thing of atm, so any help would be appreciated.
    • By Fluffee
      Fluffee's Server Setup 2.0 [BETA]
      As some of you may know, I released an automated server setup script a little over a year ago. Albeit that script worked well, I was never fully satisfied with it, as I found it to be kind of messy to use. As a result, I rewrote the script, and restructured it, to add more, and stronger support for the different versions of Debian, the different versions of CentOS and the different versions of Ubuntu. However, with so many different Operating Systems being supported, and many different server providers having different setups, it's hard for me to test every possible scenario on my own. Which is why I've been privately handing this script out, and am now publicly looking for help.

      What does the script do?
      Similar to my previous setup script, this script changes the SSH port and creates a new user for connecting and using the server and disables root SSH connections; it installs the latest version of TightVNC Server (1.3.10) and sets that up with the desired port and password. It installs JDK 102 (32 or 64 bit depending on the OS), and installs TRiBot and OSBuddy and sets up the appropriate .jar file associations.
      What operating systems does it support?
      - CentOS (6.x and 7.x) (32 and 64 bit)
      - Debian (7.x and 8.x) (32 and 64 bit)
      - Ubuntu (12.x, 14.x and 16.x) (32 and 64 bit)
      Does it work?
      As far as I know, yes it does in fact work, and it works well if I might add. However, given that I can't test every possible setup, there is the potential for differences and issues, which is why I need help.
      I want to beta test, how can I help?
      The next time you setup a server, or if you just want to reinstall your old one, use this new script and let me know if you encounter any issues or things that you think are missing. Ideally, after you answer the questions the script prompts you for, you shouldn't have to touch the keyboard again. Therefore, if during installation the script prompts you for any kind of input that isn't the first few questions, please let me know as this is probably not supposed to happen. Also, if things don't work, like TRiBot doesn't open, there's no internet browser, LG won't hook, etc. make me aware of those issues as well, so I can try and fix them!
      I've found a bug, what do you need from me?
      A few things, I'll need the operating system and bit type and a description of the bug. I may ask you for SSH access to the server, as well as ask you to reinstall the server a few times, while I attempt to troubleshoot the issue. The issues may only arise on your server, so I might not be able to recreate the issue on my end, as my hosting provider may have a different server setup than your's. I've added in a bug report format below which would be the best way to report a bug, but simply shooting me a PM or messaging me on Skype also work, assuming you're willing to allow me to troubleshoot.
       
       
      How do I run the script?
      Login as root to a fresh VPS/dedi running one of the supported operating systems. From there run the commands listed below and follow the onscreen instructions. For those who would like to see the script's code, it can be found on my github here. The commands to run are as follows:
      wget --no-check-cert https://bitbucket.org/Fluffee/fluffees-server-setup/raw/master/fluffees-server-setup.sh && chmod +x fluffees-server-setup.sh && ./fluffees-server-setup.sh -v Version History
       
    • By odisey
      Hi,
      I recently got back to Runescape because I was playing with opencv. At first, I wanted to create my own bot (something simple ) but I was amazed by the amount of work that went into Tribot antiban so I decided that I would write some scripts here.

      I used to bot on the powerbot website before 2013 and got really close to max cape back then. I had like 5 skills left.

      It could be fun to give something back to the community that created my main account that is not banned until this day.

      I have some questions if there is anyone who would make time for me.

      1) Could you please share links with some up to date comprehensive tutorial how to write a bot? I don't really code in java but the syntax is quite similar to other languages. However, it would be cool to read some tutorial for an advanced script (something more complicated than clicking tree and dropping logs) so that I could get a better feeling of a file structure, GUI, antiban and decision tree.

      2) Is Tribot color bot? How detectable is the client? I saw that you have something like looking glass? That looks really cool but on the other hand, I saw some scripts working with item ids. Do you detect items on screen or do you read environment information from computer memory?

      3) Are private scripts less detectable than public scripts?
    • By RedClifford
      Hey guys first time posting on TriBot but I am really struggling to get it to run on my Mac. It wants to run but it always encounters the same error which is it says Exception in thread "AWT-EventQue-1"java.lang.unsatisfiedlinkerror:Cant load library: / Usersxxxxxxx/Library/application support/tribot/dependancies/libtogl.so . I know that anyone with minor knowledge of computers could fix this problem in seconds, but I don't have the slightest clue as to how to fix this. All i am trying to do is run TriBot with a private proxy for RS3. If anyone can help me resolve this issue comment on here or leave another way I can contact you I'd really appreciate it. Willing to pay $10 to anyone that can help me. Thank you. 

  • Our picks

    • This release will:

      Fix bytecode manipulation in order to prevent the modification of parameters within the Filter and Condition classes themselves (thanks @wastedbro)


      Fix NPE caused by non-null value in GE API (thanks @erickho123)


      Add and fix equals methods for api2007.types (thanks @JoeDezzy1)


      Modify Mouse#leaveGame to make the mouse leave the game from top, left, right, or bottom (thanks @erickho123)


      Add Entrana area to Ships API (thanks @erickho123)


      Fix raid prayers index/settings in Prayer API (thanks @erickho123)



      Upcoming updates:

      Break handler bug fix


      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
        • Like
      • 27 replies
    • This update will:

      Implement better canvas locking/synchronization mechanism


      Fix small Login API bug


      Remove the requirement for xbooting Java classes


      Use ExecutorService to perform canvas work in parallel


      Add "Account Management" game tab to GameTab API (thanks @Encoded)


      Fix NPCChat#getMessage (thanks @Encoded )


      Fix NPCChat#selectOption (thanks @Encoded )


      Fix Banking API after today's update (thanks @Encoded )


      Fix in-game world hopper after today's update (thanks @Encoded )



      Upcoming updates:

      Break handler bug fix


      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
        • Thanks
        • Like
      • 38 replies
    • This release includes:

      Fix updater bug which was causing a bunch of issues


      TRiBot will no longer require manual hook fixes every time the RS client updates - the updater has been fully patched for objects


      Hooked login fields


      Improved the login bot


      Ability to recognize the banned/locked messages again


      Ability to read the current input for username and password fields


      If the username or password is already entered correctly, it won't be erased


      If only part of the username or password is already entered correctly, it won't be erased. The login bot will fill in what's missing.


      If there are a few invalid characters after a valid substring of your username/password, only (approximately) those invalid characters will be erased. The login bot will then proceed to fill in the missing characters.





      Coming soon:

      Skull icon fix


      Improve screen rate and responsiveness of the RS client (both regular client and LG)


      Much more
        • Thanks
        • Like
      • 33 replies
    • This release includes:

      Fix shift clicking option selecting


      Fix high paint delay settings saving


      Update prayer IDs for the quick select menu


      Remove RS3 support


      Fix hooks



      RS3 Support Removed

      The RS3 client hasn't been updated since our Old-School version of TRiBot was released, as many of you may have noticed. Keeping all of the RS3 code in the client made the client as a whole harder to maintain, larger, slower, and messier. As hardly anyone still uses the RS3 client, and since the RS3 API was hardly functioning, we made the decision to completely remove it from TRiBot.

      For the average user, this means that the client will be smaller, cleaner, and faster. Future updates will also take less work meaning there will be more frequent updates.

      If you were one of the few users still using the RS3 client, we apologize for the inconvenience. No future support for RS3 is planned. There are many other botting clients which has support for RS3, so we recommend finding an alternative if you wish to continue botting on RS3.
        • Thanks
        • Like
      • 25 replies
    • Please welcome our new developers, @JoeDezzy1, @erickho123, @Encoded, and @wastedbro.

      These members will be responsible for working on, maintaining, and improving TRiBot.

      This means that bug fixes and improvements will now come at a much faster pace! We're committed to providing users with the best botting experience possible!
        • Thanks
        • Like
      • 30 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×