package client; import client.inventory.Equip; import client.inventory.MapleInventoryType; import constants.GameConstants; import database.DatabaseConnection; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import server.MapleItemInformationProvider; import server.quest.MapleQuest; import tools.Pair; import tools.Triple; import tools.data.MaplePacketLittleEndianWriter; import tools.packet.CField; public class MonsterBook implements Serializable { private static final long serialVersionUID = 7179541993413738569L; private boolean changed = false; private int currentSet = -1; private int level = 0; private int setScore; private int finishedSets; private Map<Integer, Integer> cards; private List<Integer> cardItems = new ArrayList(); private Map<Integer, Pair<Integer, Boolean>> sets = new HashMap(); public MonsterBook(Map<Integer, Integer> cards, MapleCharacter chr) { this.cards = cards; calculateItem(); calculateScore(); MapleQuestStatus stat = chr.getQuestNoAdd(MapleQuest.getInstance(122800)); if ((stat != null) && (stat.getCustomData() != null)) { this.currentSet = Integer.parseInt(stat.getCustomData()); if ((!this.sets.containsKey(Integer.valueOf(this.currentSet))) || (!((Boolean) ((Pair) this.sets.get(Integer.valueOf(this.currentSet))).right).booleanValue())) { this.currentSet = -1; } } applyBook(chr, true); } public void applyBook(MapleCharacter chr, boolean first_login) { if (GameConstants.GMS) { Equip item = (Equip) chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -55); if (item == null) { item = (Equip) MapleItemInformationProvider.getInstance().getEquipById(1172000); item.setPosition((short) -55); } modifyBook(item); if (first_login) { chr.getInventory(MapleInventoryType.EQUIPPED).addFromDB(item); } else { chr.forceReAddItem_Book(item, MapleInventoryType.EQUIPPED); chr.equipChanged(); } } } public byte calculateScore() { byte returnval = 0; sets.clear(); int oldLevel = level, oldSetScore = setScore; setScore = 0; finishedSets = 0; final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); for (int i : cardItems) { //we need the card id but we store the mob id lol final Integer x = ii.getSetId(i); if (x != null && x.intValue() > 0) { final Triple<Integer, List<Integer>, List<Integer>> set = ii.getMonsterBookInfo(x); if (set != null) { if (!sets.containsKey(x)) { sets.put(x, new Pair<Integer, Boolean>(1, Boolean.FALSE)); } else { sets.get(x).left++; } if (sets.get(x).left == set.mid.size()) { sets.get(x).right = Boolean.TRUE; setScore += set.left; if (currentSet == -1) { currentSet = x; returnval = 2; } finishedSets++; } } } } level = 10; for (byte i = 0; i < 10; i++) { if (GameConstants.getSetExpNeededForLevel(i) > setScore) { level = (byte) i; break; } } if (level > oldLevel) { returnval = 2; } else if (setScore > oldSetScore) { returnval = 1; } return returnval; } public void writeCharInfoPacket(MaplePacketLittleEndianWriter mplew) { List cardSize = new ArrayList(10); for (int i = 0; i < 10; i++) { cardSize.add(Integer.valueOf(0)); } for (Iterator i$ = this.cardItems.iterator(); i$.hasNext();) { int x = ((Integer) i$.next()).intValue(); cardSize.set(0, Integer.valueOf(((Integer) cardSize.get(0)).intValue() + 1)); cardSize.set(x / 1000 % 10 + 1, Integer.valueOf(((Integer) cardSize.get(x / 1000 % 10 + 1)).intValue() + 1)); } for (Iterator i$ = cardSize.iterator(); i$.hasNext();) { int i = ((Integer) i$.next()).intValue(); mplew.writeInt(i); } mplew.writeInt(this.setScore); mplew.writeInt(this.currentSet); mplew.writeInt(this.finishedSets); } public void writeFinished(MaplePacketLittleEndianWriter mplew) { MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); mplew.write(1); mplew.writeShort(this.cardItems.size()); List mbList = new ArrayList(ii.getMonsterBookList()); Collections.sort(mbList); int fullCards = mbList.size() / 8 + (mbList.size() % 8 > 0 ? 1 : 0); mplew.writeShort(fullCards); for (int i = 0; i < fullCards; i++) { int currentMask = 1; int maskToWrite = 0; for (int y = i * 8; (y < i * 8 + 8) && (mbList.size() > y); y++) { if (this.cardItems.contains(mbList.get(y))) { maskToWrite |= currentMask; } currentMask *= 2; } mplew.write(maskToWrite); } int fullSize = this.cardItems.size() / 2 + (this.cardItems.size() % 2 > 0 ? 1 : 0); mplew.writeShort(fullSize); for (int i = 0; i < fullSize; i++) { mplew.write(i == this.cardItems.size() / 2 ? 1 : 17); } } public void writeUnfinished(MaplePacketLittleEndianWriter mplew) { mplew.write(0); mplew.writeShort(this.cardItems.size()); for (Iterator i$ = this.cardItems.iterator(); i$.hasNext();) { int i = ((Integer) i$.next()).intValue(); mplew.writeShort(i % 10000); mplew.write(1); } } public void calculateItem() { this.cardItems.clear(); for (Map.Entry s : this.cards.entrySet()) { addCardItem(((Integer) s.getKey()).intValue(), ((Integer) s.getValue()).intValue()); } } public void addCardItem(int key, int value) { if (value >= 2) { Integer x = MapleItemInformationProvider.getInstance().getItemIdByMob(key); if ((x != null) && (x.intValue() > 0)) { this.cardItems.add(Integer.valueOf(x.intValue())); } } } public void modifyBook(Equip eq) { eq.setStr((short) this.level); eq.setDex((short) this.level); eq.setInt((short) this.level); eq.setLuk((short) this.level); eq.setPotential1(0); eq.setPotential2(0); eq.setPotential3(0); eq.setPotential4(0); eq.setPotential5(0); if (this.currentSet > -1) { Triple set = MapleItemInformationProvider.getInstance().getMonsterBookInfo(this.currentSet); if (set != null) { for (int i = 0; i < ((List) set.right).size(); i++) { if (i == 0) { eq.setPotential1(((Integer) ((List) set.right).get(i)).intValue()); } else if (i == 1) { eq.setPotential2(((Integer) ((List) set.right).get(i)).intValue()); } else if (i == 2) { eq.setPotential3(((Integer) ((List) set.right).get(i)).intValue()); } else { if (i == 3) { break; } if (i == 4) { eq.setPotential5(((Integer) ((List) set.right).get(i)).intValue()); break; } } } } else { this.currentSet = -1; } } } public int getSetScore() { return this.setScore; } public int getLevel() { return this.level; } public int getSet() { return this.currentSet; } public boolean changeSet(int c) { if ((this.sets.containsKey(Integer.valueOf(c))) && (((Boolean) ((Pair) this.sets.get(Integer.valueOf(c))).right).booleanValue())) { this.currentSet = c; return true; } return false; } public void changed() { this.changed = true; } public Map<Integer, Integer> getCards() { return this.cards; } public final int getSeen() { return this.cards.size(); } public final int getCaught() { int ret = 0; for (Iterator i$ = this.cards.values().iterator(); i$.hasNext();) { int i = ((Integer) i$.next()).intValue(); if (i >= 2) { ret++; } } return ret; } public final int getLevelByCard(int cardid) { return this.cards.get(Integer.valueOf(cardid)) == null ? 0 : ((Integer) this.cards.get(Integer.valueOf(cardid))).intValue(); } public static final MonsterBook loadCards(int charid, MapleCharacter chr) throws SQLException { PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM monsterbook WHERE charid = ? ORDER BY cardid ASC"); ps.setInt(1, charid); ResultSet rs = ps.executeQuery(); Map cards = new LinkedHashMap(); while (rs.next()) { cards.put(Integer.valueOf(rs.getInt("cardid")), Integer.valueOf(rs.getInt("level"))); } rs.close(); ps.close(); return new MonsterBook(cards, chr); } public final void saveCards(int charid) throws SQLException { if (!this.changed) { return; } Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("DELETE FROM monsterbook WHERE charid = ?"); ps.setInt(1, charid); ps.execute(); ps.close(); this.changed = false; if (this.cards.isEmpty()) { return; } boolean first = true; StringBuilder query = new StringBuilder(); for (Map.Entry all : this.cards.entrySet()) { if (first) { first = false; query.append("INSERT INTO monsterbook VALUES (DEFAULT,"); } else { query.append(",(DEFAULT,"); } query.append(charid); query.append(","); query.append(all.getKey()); query.append(","); query.append(all.getValue()); query.append(")"); } ps = con.prepareStatement(query.toString()); ps.execute(); ps.close(); } public final boolean monsterCaught(MapleClient c, int cardid, String cardname) { if ((!this.cards.containsKey(Integer.valueOf(cardid))) || (((Integer) this.cards.get(Integer.valueOf(cardid))).intValue() < 2)) { this.changed = true; // c.getPlayer().dropMessage(-6, new StringBuilder().append("Book entry updated - ").append(cardname).toString()); c.getSession().write(CField.EffectPacket.showForeignEffect(16)); this.cards.put(Integer.valueOf(cardid), Integer.valueOf(2)); if (GameConstants.GMS) { if (c.getPlayer().getQuestStatus(50195) != 1) { MapleQuest.getInstance(50195).forceStart(c.getPlayer(), 9010000, "1"); } if (c.getPlayer().getQuestStatus(50196) != 1) { MapleQuest.getInstance(50196).forceStart(c.getPlayer(), 9010000, "1"); } addCardItem(cardid, 2); byte rr = calculateScore(); if (rr > 0) { if (c.getPlayer().getQuestStatus(50197) != 1) { MapleQuest.getInstance(50197).forceStart(c.getPlayer(), 9010000, "1"); } c.getSession().write(CField.EffectPacket.showForeignEffect(44)); if (rr > 1) { applyBook(c.getPlayer(), false); } } } return true; } return false; } public boolean hasCard(int cardid) { return this.cardItems == null ? false : this.cardItems.contains(Integer.valueOf(cardid)); } public final void monsterSeen(MapleClient c, int cardid, String cardname) { if (this.cards.containsKey(Integer.valueOf(cardid))) { return; } this.changed = true; //c.getPlayer().dropMessage(-6, new StringBuilder().append("New book entry - ").append(cardname).toString()); this.cards.put(Integer.valueOf(cardid), Integer.valueOf(1)); c.getSession().write(CField.EffectPacket.showForeignEffect(16)); } }