package net.scapeemulator.game.model.player; import java.util.HashMap; import net.scapeemulator.cache.def.ItemDefinition; import net.scapeemulator.game.content.shop.Shop; import net.scapeemulator.game.content.shop.ShopInterfaceHandler; import net.scapeemulator.game.content.shop.StockType; import net.scapeemulator.game.dispatcher.button.ButtonDispatcher; import net.scapeemulator.game.model.ExtendedOption; import net.scapeemulator.game.model.World; import net.scapeemulator.game.model.definition.ItemDefinitions; import net.scapeemulator.game.model.player.interfaces.ComponentListener; import net.scapeemulator.game.model.player.interfaces.InterfaceSet.Component; import net.scapeemulator.game.msg.impl.ScriptMessage; import net.scapeemulator.game.msg.impl.inter.InterfaceAccessMessage; import net.scapeemulator.game.msg.impl.inter.InterfaceItemsMessage; import net.scapeemulator.game.msg.impl.inter.InterfaceVisibleMessage; import net.scapeemulator.game.util.math.BasicMath; public class ShopHandler extends ComponentListener { static { ButtonDispatcher.getInstance().bind(new ShopInterfaceHandler()); } public final static HashMap<String, Shop> shops = new HashMap<String, Shop>(); private final static int[] amounts = { 1, 5, 10, 50 }; private final Player player; private Shop activeShop; private StockType activeStock; public ShopHandler(Player player) { this.player = player; } public void sell(int itemId, int amount) { if (activeShop == null) { return; } int unnotedId = ItemDefinitions.forId(itemId).getUnnotedItemId(); if (!activeShop.acceptsItem(unnotedId)) { player.sendMessage("You cannot sell that item to this shop."); return; } int itemValue = ItemDefinitions.forId(unnotedId).getLowAlchemyValue(); // Compare the amount against the amount the player actually has int playerAmount = player.getInventory().getAmount(itemId); amount = amount > playerAmount ? playerAmount : amount; // Compare the amount against the number of coins the player can hold int maxAmount = (Integer.MAX_VALUE - player.getInventory().getAmount(995)) / itemValue; amount = amount > maxAmount ? maxAmount : amount; if (amount < 1) { player.sendMessage("You cannot hold any more coins!"); return; } // Remove the items from the players inventory Item toSell = new Item(itemId, amount); Item removed = player.getInventory().remove(toSell); // Triple check that everything worked if (removed == null || !removed.equals(toSell)) { return; } // Give the player coins player.getInventory().add(new Item(995, amount * itemValue)); // Update the shop if (activeShop.add(unnotedId, toSell.getAmount()) > 0) { updateShopGlobally(); } } public void buy(int index, int amount) { if (activeShop == null) { return; } Item item = activeShop.getItemAtIndex(activeStock, index); if (item == null) { return; } int itemId = item.getId(); // ---- Start amount check ----// ItemDefinition def = ItemDefinitions.forId(itemId); int cost = def.getValue() < 1 ? 1 : def.getValue(); int assets = player.getInventory().getAmount(995); boolean coinsGone = false; if (cost * amount > assets || cost * amount < 1) { coinsGone = assets % cost == 0; amount = assets / cost; if (amount < 1) { player.sendMessage("You do not have enough coins to buy that."); return; } } int freeSlots = player.getInventory().freeSlots() + (coinsGone ? 1 : 0); if (!def.isStackable()) { amount = amount > freeSlots ? freeSlots : amount; } else { if (player.getInventory().contains(itemId)) { amount -= BasicMath.integerOverflow(player.getInventory().getAmount(itemId), amount); } else { if (freeSlots < 1) { amount = 0; } } } if (amount < 1) { player.sendMessage("You do not have any inventory space to buy that."); return; } // ---- End amount check ----// if (!activeShop.contains(activeStock, itemId)) { return; } amount = activeShop.remove(activeStock, itemId, amount); if (amount > 0 && activeStock != StockType.MAIN) { updateShopGlobally(); } player.getInventory().remove(new Item(995, cost * amount)); player.getInventory().add(new Item(itemId, amount)); } public void handleInput(int childId, final int dynamicId, ExtendedOption option) { if (activeShop == null) { return; } switch (childId) { case 7: player.getInterfaceSet().closeWindow(); break; case 23: case 24: if (activeShop.getItemAtIndex(activeStock, dynamicId) == null) { return; } ItemDefinition def = activeShop.getItemAtIndex(activeStock, dynamicId).getDefinition(); switch (option) { case ONE: int value = def.getValue() < 1 ? 1 : def.getValue(); player.sendMessage(def.getName() + " costs " + value + " coin" + (value == 1 ? "" : "s") + "."); break; case TWO: case THREE: case FOUR: buy(dynamicId, amounts[option.toInteger() - 1]); break; case FIVE: player.getScriptInput().showIntegerScriptInput(new ScriptInputListener() { @Override public void intInputReceived(int value) { buy(dynamicId, value); } @Override public void usernameInputReceived(long value) { } }); break; case SIX: player.sendMessage(def.getExamine()); break; default: return; } break; case 25: openMainStock(); break; case 26: openPlayerStock(); break; } } public void handleInventoryClick(int dynamicId, ExtendedOption option) { if (dynamicId < 0 || dynamicId > 27) { return; } final Item item = player.getInventory().get(dynamicId); if (item == null) { return; } ItemDefinition def = ItemDefinitions.forId(item.getDefinition().getUnnotedItemId()); switch (option) { case ONE: int value = (int) (def.getLowAlchemyValue()); player.sendMessage(def.getName() + " sells for " + value + " coin" + (value == 1 ? "" : "s") + "."); break; case TWO: case THREE: case FOUR: sell(item.getId(), amounts[option.toInteger() - 1]); break; case FIVE: player.getScriptInput().showIntegerScriptInput(new ScriptInputListener() { @Override public void intInputReceived(int value) { sell(item.getId(), value); } @Override public void usernameInputReceived(long value) { } }); break; case NINE: player.sendMessage(def.getExamine()); break; default: return; } } public void updateShopGlobally() { for (Player p : World.getWorld().getPlayers()) { if (p.getShopHandler().getActiveShop() == activeShop) { p.send(new InterfaceItemsMessage(31, activeShop.getStock(StockType.PLAYER))); } } } private void openPlayerStock() { if (activeStock == StockType.PLAYER) { return; } if (!activeShop.hasStock(StockType.PLAYER)) { player.sendMessage("This shop has no player stock."); return; } player.send(new InterfaceVisibleMessage(620, 23, false)); player.send(new InterfaceVisibleMessage(620, 24, true)); player.send(new InterfaceVisibleMessage(620, 29, false)); player.send(new InterfaceVisibleMessage(620, 25, true)); player.send(new InterfaceVisibleMessage(620, 27, true)); player.send(new InterfaceVisibleMessage(620, 26, false)); player.send(new InterfaceAccessMessage(620, 24, 0, 40, 1278)); activeStock = StockType.PLAYER; } private void openMainStock() { if (activeStock == StockType.MAIN) { return; } player.send(new InterfaceVisibleMessage(620, 23, true)); player.send(new InterfaceVisibleMessage(620, 24, false)); player.send(new InterfaceVisibleMessage(620, 29, true)); player.send(new InterfaceVisibleMessage(620, 25, false)); player.send(new InterfaceVisibleMessage(620, 27, false)); player.send(new InterfaceVisibleMessage(620, 26, true)); player.send(new InterfaceAccessMessage(620, 23, 0, 40, 1278)); activeStock = StockType.MAIN; } public void openShop(String shopName) { if (!shops.containsKey(shopName)) { throw new IllegalArgumentException("Invalid shop name \"" + shopName + "\""); } Shop shop = shops.get(shopName); activeShop = shop; player.send(new InterfaceItemsMessage(93, player.getInventory().toArray())); if (shop.hasStock(StockType.PLAYER)) { player.send(new InterfaceItemsMessage(31, activeShop.getStock(StockType.PLAYER))); } player.setInterfaceText(620, 22, shopName); player.send(new InterfaceVisibleMessage(620, 34, shop.hasStock(StockType.PLAYER))); player.getInterfaceSet().openWindow(620); player.getInterfaceSet().openInventory(621); player.getInterfaceSet().getWindow().setListener(this); player.send(new ScriptMessage(150, "IviiiIsssssssss", new Object[] { "", "", "", "", "Sell X", "Sell 10", "Sell 5", "Sell 1", "Value", -1, 0, 7, 4, 93, 621 << 16 })); player.send(new ScriptMessage(150, "IviiiIsssssssss", new Object[] { "", "", "", "", "Buy X", "Buy 10", "Buy 5", "Buy 1", "Value", -1, 0, 4, 10, 31, (620 << 16) + 24 })); player.send(new InterfaceAccessMessage(621, 0, 0, 27, 1278)); player.send(new InterfaceAccessMessage(621, 34, 0, 27, 2360446)); player.send(new ScriptMessage(25, "vg", new Object[] { shop.getShopId(), 93 })); openMainStock(); } public void shopScript(int id) { player.send(new ScriptMessage(25, "vg", new Object[] { id, 93 })); } public Shop getActiveShop() { return activeShop; } // This is not the same type of input as button input @Override public void inputPressed(Component component, int componentId, int dynamicId) { } @Override public void componentClosed(Component component) { activeShop = null; activeStock = null; } @Override public boolean componentChanged(Component component, int oldId) { componentClosed(component); return false; } }