import javax.swing.*; import java.awt.Graphics; import com.rsbuddy.script.Manifest; import com.rsbuddy.script.methods.Game; import com.rsbuddy.script.ActiveScript; import com.rsbuddy.script.methods.Environment; import com.rsbuddy.script.methods.Keyboard; import com.rsbuddy.script.util.Random; import com.rsbuddy.script.methods.Mouse; import com.rsbuddy.script.methods.Widgets; import com.rsbuddy.script.util.Timer; import com.rsbuddy.script.wrappers.Component; //import com.rsbuddy.event.events.*; import com.rsbuddy.script.methods.Camera; import com.rsbuddy.event.listeners.*; import org.rsbuddy.widgets.GrandExchange; import org.rsbuddy.tabs.Inventory; import com.rsbuddy.script.wrappers.Item; import org.rsbuddy.net.GeItem; /** * * @author Andre P. */ @Manifest(name = "High Frequency Trader", description = "Does micro transactions on the Grand Exchange.", authors = "Andre", version = 2.0) public class HighFrequencyTrader extends ActiveScript implements PaintListener { public static final int ABORT_OFFER_COMPONENT = 200; public enum ScriptState { NULL, START, CALCULATE_OFFER, CHECK_PRICE, BUY, SELL, CHECK_LIQUIDITY, END } @Override public boolean onStart() { Environment.disableRandom("InterfaceCloser"); try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { merchantItem = JOptionPane.showInputDialog("Enter item to merchant: "); maxBuyLimit = Integer.parseInt(JOptionPane.showInputDialog("Max Buy Limit: ")); } }); } catch (Exception e) { } Mouse.setSpeed(5); curState = ScriptState.START; prevState = ScriptState.NULL; totalCycles = 0; totalProfit = 0; return true; } @Override public int loop() { if (!Game.isLoggedIn()) { log("Waiting for player to login."); return 5000; } switch (curState) { case START: if (numTries == MAX_TRIES) { failSafe("Entered START state too many times"); } if (!GrandExchange.isOpen()) { log("Opening Grand Exchange interface..."); GrandExchange.open(); sleep(500); ++numTries; return Random.nextInt(2000, 5000); } else { log("Grand Exchange interface opened."); log("Loading item information"); item = org.rsbuddy.net.GeItem.lookup(merchantItem); while (item == null) { item = org.rsbuddy.net.GeItem.lookup(merchantItem); sleep(15); } id = item.getId(); log("done."); Item money = Inventory.getItem(GP); if (money == null) { log("Start script at Grand Exchange with money in inventory."); stop(); } startPrincipal = money.getStackSize(); prevState = curState; curState = ScriptState.CALCULATE_OFFER; } break; case CALCULATE_OFFER: while (!Widgets.getComponent(105, 18).getText().contains("Shown below is a summary")) { sleep(300); } if (abortedBuyOffer) { if (Inventory.contains(id) || Inventory.contains(id + 1)) { try { amount = Inventory.getItem(id).getStackSize(); } catch (Exception e) { amount = Inventory.getItem(id + 1).getStackSize(); } abortedBuyOffer = true; curState = ScriptState.SELL; break; } abortedBuyOffer = false; } if (abortedSellOffer) { if (Inventory.contains(id) || Inventory.contains(id + 1)) { try { amount = Inventory.getItem(id).getStackSize(); } catch (Exception e) { amount = Inventory.getItem(id + 1).getStackSize(); } abortedSellOffer = true; curState = ScriptState.SELL; break; } abortedSellOffer = false; } Item money = Inventory.getItem(GP); if (money == null) { log("Start script at Grand Exchange with money in inventory."); stop(); } principal = money.getStackSize(); log("principal: " + principal); /*if (!GrandExchange.isBuyScreenOpen()) { openBox(true, 0); } else { if (!GrandExchange.isSearchOpen()) { GrandExchange.getSearchButton().click(); sleep(Random.nextInt(500, 600)); } Keyboard.sendText(merchantItem, true); sleep(Random.nextInt(1000, 1500)); for (Component c : Widgets.get(GrandExchange.WIDGET_SEARCH).getComponent(GrandExchange.ITEM_COMPONENTS).getComponents()) { if (c.getText().toLowerCase().equals(merchantItem.toLowerCase())) { c.click(); break; } } sleep(Random.nextInt(1000, 1500)); guidePrice = GrandExchange.getPrice();*/ guidePrice = item.getGuidePrice(); sleep(Random.nextInt(1000, 1500)); //log("Guide price: " + guidePrice); prevState = curState; curState = ScriptState.CHECK_LIQUIDITY; //} break; case CHECK_LIQUIDITY: //log("Checking liquidity..."); //Buy at a 25% markup boolean success; boughtPrice = soldPrice = -1; int buyOffer = guidePrice + (int) (guidePrice * .25); int sellOffer = guidePrice - (int) (guidePrice * .25); success = buy(merchantItem, 1, buyOffer, 0); while (!success) { sleep(500); success = buy(merchantItem, 1, buyOffer, 0); } log("success"); //log("Buying 1 " + merchantItem + " for " + buyOffer + " gp."); success = waitForItem(true, 1, 0); while (!success) { sleep(500); success = waitForItem(true, 1, 0); } //log("Bought for " + boughtPrice + " gp."); //Sell at a 25% markdown success = sell(1, sellOffer, 0); while (!success) { log("sell failed"); sleep(500); success = sell(1, sellOffer, 0); } //log("Selling 1 " + merchantItem + " for " + sellOffer + " gp."); success = waitForItem(false, 1, 0); while (!success) { sleep(500); success = waitForItem(false, 1, 0); } //log("Sold for " + soldPrice + " gp."); profitMargin = boughtPrice - soldPrice; totalProfit -= profitMargin; log("profit margin: " + profitMargin); if (profitMargin < 1000) { log("Losing money merchanting " + merchantItem); log("Waiting before starting again."); sleep(15000); prevState = curState; curState = ScriptState.CALCULATE_OFFER; break; } //Account for loss in checking liquidity principal -= profitMargin; prevState = curState; curState = ScriptState.BUY; break; case BUY: buyMarkup = (int) Math.floor(profitMargin * .1); amount = maxBuyLimit;//(int) Math.floor(principal / (soldPrice + buyMarkup)); //log("Buying " + amount + " " + merchantItem + " for " + (amount * (soldPrice + buyMarkup)) + " gp."); success = buy(merchantItem, amount, soldPrice + buyMarkup, 0); while (!success) { sleep(1000); success = buy(merchantItem, amount, soldPrice + buyMarkup, 0); } success = waitForItem(true, amount, 0); while (!success) { sleep(1000); success = waitForItem(true, amount, 0); } if (abortedBuyOffer) { log("Buy offer aborted."); break; } sleep(500); //log("Bought for " + (soldPrice + buyMarkup) + " gp each."); prevState = curState; curState = ScriptState.SELL; break; case SELL: if ((Inventory.getItem(id) == null) && (Inventory.getItem(id + 1) == null) && prevState != ScriptState.CHECK_LIQUIDITY) { prevState = curState; curState = ScriptState.CALCULATE_OFFER; break; } sellMarkup = (int) Math.ceil(profitMargin * .90); if (!abortedBuyOffer && !abortedSellOffer) { amount = maxBuyLimit;//(int) Math.floor(principal / (soldPrice + buyMarkup)); } if (abortedSellOffer) { sellMarkup = buyMarkup; abortedSellOffer = false; } //log("Selling " + amount + " " + merchantItem + " for " + (amount * (soldPrice + sellMarkup))); //we add 1 to the item id because the item is noted. success = sell(amount, soldPrice + sellMarkup, 0); while (!success) { sleep(500); success = sell(amount, soldPrice + sellMarkup, 0); } success = waitForItem(false, amount, 0); while (!success) { sleep(1000); success = waitForItem(false, amount, 0); } if (abortedSellOffer) { log("Sell offer aborted."); break; } //log("Sold for " + (soldPrice + sellMarkup) + " gp each."); //log("Profit cycle complete made: " + ((amount * (soldPrice + sellMarkup)) - (amount * (soldPrice + buyMarkup)) - profitMargin) + "gp."); ++totalCycles; //log("Total # of cycles: " + totalCycles); totalProfit += ((amount * (soldPrice + sellMarkup)) - (amount * (soldPrice + buyMarkup))); //log("Total profit: " + totalProfit); abortedBuyOffer = false; abortedSellOffer = false; prevState = curState; curState = ScriptState.CALCULATE_OFFER; break; case END: stop(); break; default: //none break; } return Random.nextInt(1500, 2000); } @Override public void onFinish() { log("Stopping script."); } private void failSafe(String message) { log(message); stop(); } @Override public void onRepaint(Graphics g) { g.drawString("Start Principal: " + startPrincipal, 10, 100); g.drawString("Current Principal: " + principal, 10, 120); g.drawString("Total Profit: " + totalProfit, 10, 140); } //slot parameter indexing starts at 0 public boolean waitForItem(boolean buy, int count, int slot) { int bPrice = -1, sPrice = -1; Component c = Widgets.getComponent(GrandExchange.WIDGET, GrandExchange.OFFER_TABS[slot]); while (c == null || !c.isValid() || !c.isVisible()) { sleep(15); } if (Widgets.get(GrandExchange.WIDGET).getComponent(GrandExchange.OFFER_TABS/*BUY_BOXES*/[slot]).interact("View Offer")) { sleep(2000); Timer maxTimeout = null; if (profitMargin < 5000) { maxTimeout = new Timer(270000); } else { maxTimeout = new Timer(480000); } Timer timeout; if (buy) { timeout = new Timer(120000); } else { timeout = new Timer(120000); } int curProgressBarWidth = 0; int prevProgressBarWidth = 0; boolean firstMove = false; /*while ( (Widgets.get(GrandExchange.WIDGET).getComponent(199).getComponent(2) == null) || (curProgressBarWidth = Widgets.get(GrandExchange.WIDGET).getComponent(199).getComponent(2).getWidth()) < 298 ) { */ while ((c = Widgets.getComponent(GrandExchange.WIDGET, 198)) == null || !c.isValid() || !c.isVisible() || c.getText().contains("have")) { if (!maxTimeout.isRunning() || !timeout.isRunning()) { abortOffer(buy, count); return true; } if ((maxTimeout.getElapsed() > 240000) && !firstMove) { Camera.moveRandomly(2000); firstMove = true; } if (curProgressBarWidth > prevProgressBarWidth) { timeout.reset(); } prevProgressBarWidth = curProgressBarWidth; while (((Widgets.get(GrandExchange.WIDGET).getComponent(199).getComponent(2)) == null)) { sleep(50); } curProgressBarWidth = Widgets.get(GrandExchange.WIDGET).getComponent(199).getComponent(2).getWidth(); sleep(50); } if (buy) { bPrice = parsePrice(Widgets.get(105).getComponent(198).getText()); } else { sPrice = parsePrice(Widgets.get(105).getComponent(198).getText()); } int[] cs = {206, 208}; for (int i = 0; i < cs.length; i++) { if (Widgets.get(GrandExchange.WIDGET).getComponent(cs[i]).getItemId() != -1) { if (Widgets.get(GrandExchange.WIDGET).getComponent(cs[i]).getItemId() == 995) { Widgets.get(GrandExchange.WIDGET).getComponent(cs[i]).click(); } else { if (Widgets.get(GrandExchange.WIDGET).getComponent(cs[i]).getItemStackSize() == count) { Widgets.get(GrandExchange.WIDGET).getComponent(cs[i]).click(); } } } } if (buy && bPrice != -1) { if (curState == ScriptState.CHECK_LIQUIDITY) { this.boughtPrice = bPrice; } return true; } else if (!buy && sPrice != -1) { if (curState == ScriptState.CHECK_LIQUIDITY) { this.soldPrice = sPrice; } return true; } } return false; } /*public boolean sell(int count, int price, int slot) { if (GrandExchange.isOpen()) { Component c = Widgets.getComponent(GrandExchange.WIDGET, GrandExchange.BUTTON_SEARCH); if (c != null && c.isValid() && c.isVisible()) { if (GrandExchange.getSearchButton().getItemId() == id || GrandExchange.getSearchButton().getItemId() == (id + 1)) { if (GrandExchange.setCount(count)) { sleep(100); if (GrandExchange.setPrice(price)) { sleep(100); if (GrandExchange.confirmOffer()) { return true; } } } } else { while (Inventory.getItem(id) == null && Inventory.getItem(id + 1) == null) { sleep(50); } try { Inventory.getItem(id).click(true); } catch (Exception e) { Inventory.getItem(id + 1).click(true); } return sell(count, price, 0); } } else { openBox(false, slot); Timer timeout = new Timer(5000); Component c2 = null; while (((c2 = Widgets.getComponent(GrandExchange.WIDGET, GrandExchange.BUTTON_SEARCH)) == null || !c2.isValid() || !c2.isVisible()) && timeout.isRunning()) { sleep(15); } return sell(count, price, 0); } } else { GrandExchange.open(); while (!GrandExchange.isOpen()) { sleep(15); } return sell(count, price, 0); } return false; }*/ public boolean sell(int count, int price, int slot) { while (!(openBox(false, slot) == slot)) { sleep(1000); } Component c2 = null; while (((c2 = Widgets.getComponent(GrandExchange.WIDGET, GrandExchange.BUTTON_SEARCH)) == null || !c2.isValid() || !c2.isVisible())) { sleep(15); } if (Inventory.getItem(id) == null && Inventory.getItem(id + 1) == null) { sleep(50); } try { Inventory.getItem(id).click(true); sleep(800); } catch (Exception e) { Inventory.getItem(id + 1).click(true); sleep(800); } while (!Widgets.getComponent(GrandExchange.WIDGET, 142).getText().toLowerCase().equals(merchantItem.toLowerCase())) { sleep(15); } Component c = Widgets.getComponent(GrandExchange.WIDGET, 134); if (c.getText().equals("Sell Offer") && c.isVisible()) { if (setCount(count)) { sleep(100); if (setPrice(price)) { sleep(100); if (GrandExchange.confirmOffer()) { return true; } } } } //click back button. Widgets.getComponent(GrandExchange.WIDGET, 128).click(); sleep(3000); return false; } private static int parsePrice(String text) { String line_2 = text.split("