package server.shops; import client.MapleClient; import client.SkillFactory; import client.inventory.Item; import client.inventory.MapleInventoryIdentifier; import client.inventory.MapleInventoryType; import client.inventory.MaplePet; import constants.GameConstants; import custom.MoonlightRevamp; import custom.MoonlightRevamp.MoonlightShop; import database.DatabaseConnection; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import server.MapleInventoryManipulator; import server.MapleItemInformationProvider; import tools.FileoutputUtil; import tools.Pair; import tools.packet.CField; import tools.packet.CWvsContext; public class MapleShop { private static final Set<Integer> rechargeableItems = new LinkedHashSet(); private final int id; private final int npcId; private final List<MapleShopItem> items = new LinkedList(); private final List<Pair<Integer, String>> ranks = new ArrayList(); static { rechargeableItems.add(Integer.valueOf(2070000)); rechargeableItems.add(Integer.valueOf(2070001)); rechargeableItems.add(Integer.valueOf(2070002)); rechargeableItems.add(Integer.valueOf(2070003)); rechargeableItems.add(Integer.valueOf(2070004)); rechargeableItems.add(Integer.valueOf(2070005)); rechargeableItems.add(Integer.valueOf(2070006)); rechargeableItems.add(Integer.valueOf(2070007)); rechargeableItems.add(Integer.valueOf(2070008)); rechargeableItems.add(Integer.valueOf(2070009)); rechargeableItems.add(Integer.valueOf(2070010)); rechargeableItems.add(Integer.valueOf(2070011)); rechargeableItems.add(Integer.valueOf(2070023)); rechargeableItems.add(Integer.valueOf(2070024)); rechargeableItems.add(Integer.valueOf(2330000)); rechargeableItems.add(Integer.valueOf(2330001)); rechargeableItems.add(Integer.valueOf(2330002)); rechargeableItems.add(Integer.valueOf(2330003)); rechargeableItems.add(Integer.valueOf(2330004)); rechargeableItems.add(Integer.valueOf(2330005)); rechargeableItems.add(Integer.valueOf(2330008)); rechargeableItems.add(Integer.valueOf(2331000)); rechargeableItems.add(Integer.valueOf(2332000)); } public MapleShop(int id, int npcId) { this.id = id; this.npcId = npcId; } public void addItem(MapleShopItem item) { this.items.add(item); } public List<MapleShopItem> getItems() { return this.items; } public void sendShop(MapleClient c) { c.getPlayer().setShop(this); c.getSession().write(CField.NPCPacket.getNPCShop(getNpcId(), this, c)); } public void sendShop(MapleClient c, int customNpc) { c.getPlayer().setShop(this); c.getSession().write(CField.NPCPacket.getNPCShop(customNpc, this, c)); } public void buy(MapleClient c, short slot, int itemId, short quantity) { if ((itemId / 10000 == 190) && (!GameConstants.isMountItemAvailable(itemId, c.getPlayer().getJob()))) { c.getPlayer().dropMessage(1, "You may not buy this item."); c.getSession().write(CWvsContext.enableActions()); return; } MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); int x = 0; int index = -1; for (Item i : c.getPlayer().getRebuy()) { if (i.getItemId() == itemId) { index = x; break; } x++; } if (index >= 0) { Item i = (Item) c.getPlayer().getRebuy().get(index); int price = (int) Math.max(Math.ceil(ii.getPrice(itemId) * (GameConstants.isRechargable(itemId) ? 1 : i.getQuantity())), 0.0D); if ((price >= 0) && (c.getPlayer().getMeso() >= price)) { if (MapleInventoryManipulator.checkSpace(c, itemId, i.getQuantity(), i.getOwner())) { c.getPlayer().gainMeso(-price, false); MapleInventoryManipulator.addbyItem(c, i); c.getPlayer().getRebuy().remove(index); c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 0, this, c, x)); } else { c.getPlayer().dropMessage(1, "Your inventory is full."); c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 0, this, c, -1)); } } else { c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 0, this, c, -1)); } return; } //MapleShopItem item = findById(itemId); MapleShopItem item = findBySlot(slot); quantity *= item.getQuantity(); if (item == null) { System.out.println("error shop"); } if ((item != null) && (item.getPrice() > 0) && (item.getReqItem() == 0)) { if (item.getRank() >= 0) { boolean passed = true; int y = 0; for (Pair i : getRanks()) { if ((c.getPlayer().haveItem(((Integer) i.left).intValue(), 1, true, true)) && (item.getRank() >= y)) { passed = true; break; } y++; } if (!passed) { c.getPlayer().dropMessage(1, "You need a higher rank."); c.getSession().write(CWvsContext.enableActions()); return; } } int price = GameConstants.isRechargable(itemId) ? item.getPrice() : item.getPrice() * quantity; if ((price >= 0) && (c.getPlayer().getMeso() >= price)) { if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) { c.getPlayer().gainMeso(-price, false); if (GameConstants.isPet(itemId)) { MapleInventoryManipulator.addById(c, itemId, (short) (quantity * item.getQuantity()), "", MaplePet.createPet(itemId, MapleInventoryIdentifier.getInstance()), -1, false, "Bought from shop " + id + ", " + npcId + " on " + FileoutputUtil.CurrentReadable_Date()); } else { if (GameConstants.isRechargable(itemId)) { quantity = ii.getSlotMax(item.getItemId()); } MapleInventoryManipulator.addById(c, itemId, quantity, "Bought from shop " + this.id + ", " + this.npcId + " on " + FileoutputUtil.CurrentReadable_Date()); } } else { c.getPlayer().dropMessage(1, "Your Inventory is full"); } c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 0, this, c, -1)); } } else if ((item != null) && (item.getReqItem() > 0) && (quantity == 1) && (c.getPlayer().haveItem(item.getReqItem(), item.getReqItemQ(), false, true))) { if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) { MapleInventoryManipulator.removeById(c, GameConstants.getInventoryType(item.getReqItem()), item.getReqItem(), item.getReqItemQ(), false, false); if (GameConstants.isPet(itemId)) { MapleInventoryManipulator.addById(c, itemId, (short) (quantity * item.getQuantity()), "", MaplePet.createPet(itemId, MapleInventoryIdentifier.getInstance()), -1, false, "Bought from shop " + id + ", " + npcId + " on " + FileoutputUtil.CurrentReadable_Date()); } else { if (GameConstants.isRechargable(itemId)) { quantity = ii.getSlotMax(item.getItemId()); } MapleInventoryManipulator.addById(c, itemId, quantity, "Bought from shop " + this.id + ", " + this.npcId + " on " + FileoutputUtil.CurrentReadable_Date()); } } else { c.getPlayer().dropMessage(1, "Your Inventory is full"); } c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 0, this, c, -1)); } } public void sell(MapleClient c, MapleInventoryType type, byte slot, short quantity) { if ((quantity == 65535) || (quantity == 0)) { quantity = 1; } Item item = c.getPlayer().getInventory(type).getItem((short) slot); if (item == null) { return; } if ((GameConstants.isThrowingStar(item.getItemId())) || (GameConstants.isBullet(item.getItemId()))) { quantity = item.getQuantity(); } short iQuant = item.getQuantity(); if (iQuant == 65535) { iQuant = 1; } MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); if ((ii.cantSell(item.getItemId())) || (GameConstants.isPet(item.getItemId()))) { return; } List<Item> listRebuy = new ArrayList<>(); if ((quantity <= iQuant) && (iQuant > 0)) { if (GameConstants.GMS) { if (item.getQuantity() == quantity) { if (c.getPlayer().getRebuy().size() < 10) { c.getPlayer().getRebuy().add(item.copy()); } else if (c.getPlayer().getRebuy().size() == 10) { for (int i = 1; i < 10; i++) { listRebuy.add(c.getPlayer().getRebuy().get(i)); } listRebuy.add(item.copy()); c.getPlayer().setRebuy(listRebuy); } else { int x = c.getPlayer().getRebuy().size(); for (int i = x - 10; i < x; i++) { listRebuy.add(c.getPlayer().getRebuy().get(i)); } c.getPlayer().setRebuy(listRebuy); } } else { c.getPlayer().getRebuy().add(item.copyWithQuantity(quantity)); } } MapleInventoryManipulator.removeFromSlot(c, type, (short) slot, quantity, false); double price; if (!"".equals(item.getGMLog())) { if (item.getGMLog().toUpperCase().startsWith("DROP")) { if ((GameConstants.isThrowingStar(item.getItemId())) || (GameConstants.isBullet(item.getItemId()))) { price = ii.getWholePrice(item.getItemId()) / ii.getSlotMax(item.getItemId()); } else { price = ii.getPrice(item.getItemId()); } } else { price = 1.0D; } } else { if ((GameConstants.isThrowingStar(item.getItemId())) || (GameConstants.isBullet(item.getItemId()))) { price = ii.getWholePrice(item.getItemId()) / ii.getSlotMax(item.getItemId()); } else { price = ii.getPrice(item.getItemId()); } } int recvMesos = (int) Math.max(Math.ceil(price * quantity), 0.0D); if ((price != -1.0D) && (recvMesos > 0)) { c.getPlayer().gainMeso(recvMesos, false); } c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 5, this, c, -1)); } } public void recharge(MapleClient c, byte slot) { Item item = c.getPlayer().getInventory(MapleInventoryType.USE).getItem((short) slot); if ((item == null) || ((!GameConstants.isThrowingStar(item.getItemId())) && (!GameConstants.isBullet(item.getItemId())))) { return; } MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); short slotMax = ii.getSlotMax(item.getItemId()); int skill = GameConstants.getMasterySkill(c.getPlayer().getJob()); if (skill != 0) { slotMax = (short) (slotMax + c.getPlayer().getTotalSkillLevel(SkillFactory.getSkill(skill)) * 10); } if (item.getQuantity() < slotMax) { int price = (int) Math.round(ii.getPrice(item.getItemId()) * (slotMax - item.getQuantity())); if (c.getPlayer().getMeso() >= price) { item.setQuantity(slotMax); c.getSession().write(CWvsContext.InventoryPacket.updateInventorySlot(MapleInventoryType.USE, item, false)); c.getPlayer().gainMeso(-price, false, false); c.getSession().write(CField.NPCPacket.confirmShopTransaction((byte) 0, this, c, -1)); } } } protected MapleShopItem findById(int itemId) { for (MapleShopItem item : this.items) { if (item.getItemId() == itemId) { return item; } } return null; } protected MapleShopItem findBySlot(short slot) { for (MapleShopItem item : this.items) { if (item.getSlot() == slot) { return item; } } return null; } public static MapleShop createFromDB(int id, boolean isShopId) { MapleShop ret = null; MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); try { Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement(isShopId ? "SELECT * FROM shops WHERE shopid = ?" : "SELECT * FROM shops WHERE npcid = ?"); int shopId; ps.setInt(1, id); ResultSet rs = ps.executeQuery(); if (rs.next()) { shopId = rs.getInt("shopid"); ret = new MapleShop(shopId, rs.getInt("npcid")); rs.close(); ps.close(); } else { rs.close(); ps.close(); return null; } ps = con.prepareStatement("SELECT * FROM shopitems WHERE shopid = ? ORDER BY position ASC"); ps.setInt(1, shopId); rs = ps.executeQuery(); List<Integer> recharges = new ArrayList(rechargeableItems); while (rs.next()) { if (ii.itemExists(rs.getInt("itemid"))) { if ((GameConstants.isThrowingStar(rs.getInt("itemid"))) || (GameConstants.isBullet(rs.getInt("itemid")))) { MapleShopItem starItem = new MapleShopItem((short) rs.getShort("buyable"), ii.getSlotMax(rs.getInt("itemid")), rs.getInt("itemid"), rs.getInt("price"), (short) rs.getInt("position"), rs.getInt("reqitem"), rs.getInt("reqitemq"), rs.getByte("rank"), rs.getInt("category"), rs.getInt("minLevel"), rs.getInt("expiration"), false); ret.addItem(starItem); if (rechargeableItems.contains(Integer.valueOf(starItem.getItemId()))) { recharges.remove(Integer.valueOf(starItem.getItemId())); } } else { ret.addItem(new MapleShopItem((short) rs.getShort("buyable"), rs.getShort("quantity"), rs.getInt("itemid"), rs.getInt("price"), (short) rs.getInt("position"), rs.getInt("reqitem"), rs.getInt("reqitemq"), rs.getByte("rank"), rs.getInt("category"), rs.getInt("minLevel"), rs.getInt("expiration"), false)); //todo potential } } } for (Integer recharge : recharges) { ret.addItem(new MapleShopItem((short) 1, ii.getSlotMax(recharge.intValue()), recharge.intValue(), 0, (short) 0, 0, 0, (byte) 0, 0, 0, 0, false)); } rs.close(); ps.close(); ps = con.prepareStatement("SELECT * FROM shopranks WHERE shopid = ? ORDER BY rank ASC"); ps.setInt(1, shopId); rs = ps.executeQuery(); while (rs.next()) { if (ii.itemExists(rs.getInt("itemid"))) { ret.ranks.add(new Pair(Integer.valueOf(rs.getInt("itemid")), rs.getString("name"))); } } rs.close(); ps.close(); } catch (SQLException e) { System.err.println("Could not load shop"); } return ret; } public static MapleShop moonlightShop(int npc) { //No ranks/rechargable items for now MapleShop moonlight = new MapleShop(MoonlightRevamp.shopId, npc); for (MoonlightShop item : MoonlightShop.values()) { moonlight.addItem(new MapleShopItem((short) item.getBuyable(), (short) 1, item.getItemId(), item.getPrice(), (short) 0, item.getReqItem(), item.getReqItemQ(), item.getRank(), item.getCategory(), item.getMinLevel(), item.getExpiration(), false)); } return moonlight; } public int getNpcId() { return this.npcId; } public int getId() { return this.id; } public List<Pair<Integer, String>> getRanks() { return this.ranks; } }