package handling.channel.handler; import client.BuddyList; import client.BuddylistEntry; import client.CharacterNameAndId; import client.MapleCharacter; import client.MapleClient; import database.DatabaseConnection; import handling.channel.ChannelServer; import handling.world.WorldBuddyService; import handling.world.WorldFindService; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import tools.data.input.SeekableLittleEndianAccessor; import tools.packet.BuddyListPacket; public class BuddyListHandler { private static CharacterIdNameBuddyCapacity getCharacterIdAndNameFromDatabase(String name, String group) throws SQLException { CharacterIdNameBuddyCapacity ret; try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM characters WHERE name LIKE ?")) { ps.setString(1, name); try (ResultSet rs = ps.executeQuery()) { ret = null; if ((rs.next()) && (rs.getInt("gm") < 3)) { ret = new CharacterIdNameBuddyCapacity(rs.getInt("id"), rs.getString("name"), group, rs.getInt("buddyCapacity")); } } ps.close(); } return ret; } public static void BuddyOperation(SeekableLittleEndianAccessor slea, MapleClient c) { int mode = slea.readByte(); BuddyList buddylist = c.getPlayer().getBuddylist(); /* 0x15 好友满 0x16 对方好友满 0x17 已是好友 0x18 已申请账号好友 0x19 等待通过好友申请 0x1C 角色不存在 */ if (mode == 1) {//添加好友 String addName = slea.readMapleAsciiString(); String groupName = slea.readMapleAsciiString(); String remark = slea.readMapleAsciiString(); String alias = null; if (slea.readByte() == 1) { alias = slea.readMapleAsciiString(); } if (alias != null) { c.getPlayer().dropMessage(1, "暂时不支持账号综合好友的功能。"); return; } BuddylistEntry ble = buddylist.get(addName); if (addName.getBytes().length > 13 || groupName.getBytes().length > 16 || (alias != null && alias.getBytes().length > 13) || remark.getBytes().length > 133) { return; } if ((ble != null) && ((ble.getGroup().equals(groupName)) || (!ble.isVisible()))) { c.getSession().write(BuddyListPacket.buddylistMessage(alias != null ? 0x18 : 0x19)); } else if ((ble != null) && (ble.isVisible())) { ble.setGroup(groupName); c.getSession().write(BuddyListPacket.updateBuddylist(buddylist.getBuddies(), 0x11, false, c.getPlayer().getId())); } else if (buddylist.isFull()) { c.getSession().write(BuddyListPacket.buddylistMessage(0x15)); } else { try { CharacterIdNameBuddyCapacity charWithId = null; int channel = WorldFindService.getInstance().findChannel(addName); if (channel > 0) { MapleCharacter otherChar = ChannelServer.getInstance(channel).getPlayerStorage().getCharacterByName(addName); if (otherChar == null) { charWithId = getCharacterIdAndNameFromDatabase(addName, groupName); } else if ((!otherChar.isIntern()) || (c.getPlayer().isIntern())) { charWithId = new CharacterIdNameBuddyCapacity(otherChar.getId(), otherChar.getName(), groupName, otherChar.getBuddylist().getCapacity()); } } else { charWithId = getCharacterIdAndNameFromDatabase(addName, groupName); } if (charWithId != null) { BuddyList.BuddyAddResult buddyAddResult = null; //被加方处理 if (channel > 0) { buddyAddResult = WorldBuddyService.getInstance().requestBuddyAdd(addName, c.getChannel(), c.getPlayer().getId(), c.getPlayer().getName(), c.getPlayer().getLevel(), c.getPlayer().getJob()); MapleCharacter chr = ChannelServer.getInstance(channel).getPlayerStorage().getCharacterByName(addName); chr.getClient().getSession().write(BuddyListPacket.requestBuddylistAdd(c.getPlayer().getId(), c.getPlayer().getName(), -1)); } else { Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) as buddyCount FROM buddies WHERE characterid = ? AND pending = 0"); ps.setInt(1, charWithId.getId()); ResultSet rs = ps.executeQuery(); if (!rs.next()) { ps.close(); rs.close(); throw new RuntimeException("Result set expected"); } int count = rs.getInt("buddyCount"); if (count >= charWithId.getBuddyCapacity()) { buddyAddResult = BuddyList.BuddyAddResult.好友列表已满; } rs.close(); ps.close(); ps = con.prepareStatement("SELECT pending FROM buddies WHERE characterid = ? AND buddyid = ?"); ps.setInt(1, charWithId.getId()); ps.setInt(2, c.getPlayer().getId()); rs = ps.executeQuery(); if (rs.next()) { buddyAddResult = BuddyList.BuddyAddResult.已经是好友关系; } rs.close(); ps.close(); } //加好友方处理 if (buddyAddResult == BuddyList.BuddyAddResult.好友列表已满) {//对方好友列表已满 c.getSession().write(BuddyListPacket.buddylistMessage(0x16));//0x19-3 } else { int displayChannel = -1; int otherCid = charWithId.getId(); if ((buddyAddResult == BuddyList.BuddyAddResult.已经是好友关系) && (channel > 0)) { displayChannel = channel; notifyRemoteChannel(c, channel, otherCid, groupName, BuddyList.BuddyOperation.添加好友); } else if (buddyAddResult != BuddyList.BuddyAddResult.已经是好友关系) { Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("INSERT INTO buddies (`characterid`, `buddyid`, `groupname`, `pending`) VALUES (?, ?, ?, 1)")) { ps.setInt(1, charWithId.getId()); ps.setInt(2, c.getPlayer().getId()); ps.setString(3, groupName); ps.executeUpdate(); ps.close(); } } buddylist.put(new BuddylistEntry(charWithId.getName(), otherCid, groupName, displayChannel, true)); c.getSession().write(BuddyListPacket.requestBuddylistAdd(otherCid, charWithId.getName(), displayChannel)); //c.getSession().write(BuddyListPacket.updateBuddylist(buddylist.getBuddies(), 0x11, false, c.getPlayer().getId())); c.getSession().write(BuddyListPacket.buddylistPrompt(0x14, charWithId.getName()));//向charWithId.getName()发送了好友申请。 } } else {//角色不存在 c.getSession().write(BuddyListPacket.buddylistMessage(0x1C));//0x19+3 } } catch (SQLException e) { System.err.println("SQL THROW" + e); } } } else if (mode == 2) {//同意添加好友 int otherCid = slea.readInt(); BuddylistEntry ble = buddylist.get(otherCid); if (!buddylist.isFull() && ble != null && !ble.isVisible()) { int channel = WorldFindService.getInstance().findChannel(otherCid); buddylist.put(new BuddylistEntry(ble.getName(), otherCid, "未指定群组", channel, true)); c.getSession().write(BuddyListPacket.requestBuddylistAdd(otherCid, ble.getName(), channel)); //c.getSession().write(BuddyListPacket.updateBuddylist(buddylist.getBuddies(), 0x11, false, c.getPlayer().getId())); notifyRemoteChannel(c, channel, otherCid, "未指定群组", BuddyList.BuddyOperation.添加好友); } else { c.getSession().write(BuddyListPacket.buddylistMessage(0x16)); } } else if (mode == 4) {//删除好友 int otherCid = slea.readInt(); BuddylistEntry blz = buddylist.get(otherCid); if ((blz != null) && (blz.isVisible())) { notifyRemoteChannel(c, WorldFindService.getInstance().findChannel(otherCid), otherCid, blz.getGroup(), BuddyList.BuddyOperation.删除好友); } buddylist.remove(otherCid); c.getSession().write(BuddyListPacket.updateBuddylist(null, 0x22, true, otherCid)); } else if (mode == 6) {//拒绝添加好友 int fromCid = slea.readInt(); buddylist.remove(fromCid); c.getSession().write(BuddyListPacket.updateBuddylist(null, 0x22, true, fromCid)); MapleCharacter from = MapleCharacter.getOnlineCharacterById(fromCid); if (from == null) { return; } from.getBuddylist().remove(c.getPlayer().getId()); from.getClient().getSession().write(BuddyListPacket.updateBuddylist(null, 0x22, true, c.getPlayer().getId())); from.getClient().getSession().write(BuddyListPacket.buddylistPrompt(0x29, c.getPlayer().getName()));//c.getPlayer().getName()拒绝了好友申请。 } else if (mode == 0xA) {//增加好友上限 int capacity = c.getPlayer().getBuddyCapacity(); if ((capacity >= 100) || (c.getPlayer().getMeso() < 50000)) { c.getPlayer().dropMessage(1, "金币不足,或已扩充达到上限。包括基本格数在内,好友目录中只能加入100个好友。您当前的好友数量为: " + capacity); } else { int newcapacity = capacity + 5; c.getPlayer().gainMeso(-50000, true, true); c.getPlayer().setBuddyCapacity((byte) newcapacity); } } else { System.err.println("未处理好友操作码:" + mode); } } private static void notifyRemoteChannel(MapleClient c, int remoteChannel, int otherCid, String group, BuddyList.BuddyOperation operation) { MapleCharacter player = c.getPlayer(); if (remoteChannel > 0) { WorldBuddyService.getInstance().buddyChanged(otherCid, player.getId(), player.getName(), c.getChannel(), operation, group); } } private static final class CharacterIdNameBuddyCapacity extends CharacterNameAndId { private final int buddyCapacity; public CharacterIdNameBuddyCapacity(int id, String name, String group, int buddyCapacity) { super(id, name, group); this.buddyCapacity = buddyCapacity; } public int getBuddyCapacity() { return this.buddyCapacity; } } }