package handling.world.guild; import client.MapleCharacter; import client.MapleCharacterUtil; import client.MapleClient; import client.SkillFactory; import constants.GameConstants; import database.DatabaseConnection; import handling.world.WorldBroadcastService; import handling.world.WorldGuildService; 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.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.log4j.Logger; import server.MapleStatEffect; import tools.FileoutputUtil; import tools.MaplePacketCreator; import tools.data.output.MaplePacketLittleEndianWriter; import tools.packet.GuildPacket; import tools.packet.PacketHelper; import tools.packet.UIPacket; public class MapleGuild implements Serializable { public static final long serialVersionUID = 6322150443228168192L; private final List<MapleGuildCharacter> members = new CopyOnWriteArrayList(); private final String[] rankTitles = new String[5]; private String name; private String notice; private int id; private int gp; private int logo; private int logoColor; private int leader; private int capacity; private int logoBG; private int logoBGColor; private int signature; private int level; private boolean bDirty = true; private boolean proper = true; private int allianceid = 0; private int invitedid = 0; private final Map<Integer, MapleBBSThread> bbs = new HashMap(); private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private boolean init = false; private boolean changed = false; private static final Logger log = Logger.getLogger(MapleGuild.class); private List<Integer> joinList = new ArrayList<>(); public MapleGuild(int guildid) { this(guildid, null); } public MapleGuild(int guildid, Map<Integer, Map<Integer, MapleBBSReply>> replies) { try { Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("SELECT * FROM questinfo WHERE customData = ?"); ps.setString(1, "GuildID=" + guildid); ResultSet rs = ps.executeQuery(); while (rs.next()) { addJoinList(rs.getInt("characterid")); } rs.close(); ps.close(); ps = con.prepareStatement("SELECT * FROM guilds WHERE guildid = ?"); ps.setInt(1, guildid); rs = ps.executeQuery(); if (!rs.first()) { rs.close(); ps.close(); this.id = -1; return; } this.id = guildid; this.name = rs.getString("name"); this.gp = rs.getInt("GP"); this.logo = rs.getInt("logo"); this.logoColor = rs.getInt("logoColor"); this.logoBG = rs.getInt("logoBG"); this.logoBGColor = rs.getInt("logoBGColor"); this.capacity = rs.getInt("capacity"); this.rankTitles[0] = rs.getString("rank1title"); this.rankTitles[1] = rs.getString("rank2title"); this.rankTitles[2] = rs.getString("rank3title"); this.rankTitles[3] = rs.getString("rank4title"); this.rankTitles[4] = rs.getString("rank5title"); this.leader = rs.getInt("leader"); this.notice = rs.getString("notice"); this.signature = rs.getInt("signature"); this.allianceid = rs.getInt("alliance"); rs.close(); ps.close(); this.allianceid = 0; ps = con.prepareStatement("SELECT id, name, level, job, guildrank, guildContribution, alliancerank FROM characters WHERE guildid = ? ORDER BY guildrank ASC, name ASC", 1008); ps.setInt(1, guildid); rs = ps.executeQuery(); if (!rs.first()) { System.err.println(new StringBuilder().append("家族ID: ").append(this.id).append(" 没用成员,系统自动解散该家族。").toString()); rs.close(); ps.close(); writeToDB(true); this.proper = false; return; } boolean leaderCheck = false; byte gFix = 0; byte aFix = 0; do { int chrId = rs.getInt("id"); byte gRank = rs.getByte("guildrank"); byte aRank = rs.getByte("alliancerank"); if (chrId == this.leader) { leaderCheck = true; if (gRank != 1) { gRank = 1; gFix = 1; } } else { if (gRank == 1) { gRank = 2; gFix = 2; } if (aRank < 3) { aRank = 3; aFix = 3; } } this.members.add(new MapleGuildCharacter(chrId, rs.getShort("level"), rs.getString("name"), (byte) -1, rs.getInt("job"), gRank, rs.getInt("guildContribution"), aRank, guildid, false)); } while (rs.next()); rs.close(); ps.close(); if (!leaderCheck) { System.err.println(new StringBuilder().append("族长[ ").append(this.leader).append(" ]没有在家族ID为 ").append(this.id).append(" 的家族中,系统自动解散这个家族。").toString()); writeToDB(true); this.proper = false; return; } if (gFix > 0) { ps = con.prepareStatement("UPDATE characters SET guildrank = ? WHERE id = ?"); ps.setByte(1, gFix); ps.setInt(2, this.leader); ps.executeUpdate(); ps.close(); } if (aFix > 0) { ps = con.prepareStatement("UPDATE characters SET alliancerank = ? WHERE id = ?"); ps.setByte(1, aFix); ps.setInt(2, this.leader); ps.executeUpdate(); ps.close(); } ps = con.prepareStatement("SELECT * FROM bbs_threads WHERE guildid = ? ORDER BY localthreadid DESC"); ps.setInt(1, guildid); rs = ps.executeQuery(); while (rs.next()) { int tID = rs.getInt("localthreadid"); MapleBBSThread thread = new MapleBBSThread(tID, rs.getString("name"), rs.getString("startpost"), rs.getLong("timestamp"), guildid, rs.getInt("postercid"), rs.getInt("icon")); if ((replies != null) && (replies.containsKey(rs.getInt("threadid")))) { thread.replies.putAll((Map) replies.get(rs.getInt("threadid"))); } this.bbs.put(tID, thread); } rs.close(); ps.close(); this.level = calculateLevel(); } catch (SQLException se) { log.error(new StringBuilder().append("[MapleGuild] 从数据库中加载家族信息出错.").append(se).toString()); } } public boolean isProper() { return this.proper; } public static void loadAll() { Map replies = new LinkedHashMap(); try { Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("SELECT * FROM bbs_replies"); ResultSet rs = ps.executeQuery(); while (rs.next()) { int tID = rs.getInt("threadid"); Map reply = (Map) replies.get(Integer.valueOf(tID)); if (reply == null) { reply = new HashMap(); replies.put(tID, reply); } reply.put(reply.size(), new MapleBBSReply(reply.size(), rs.getInt("postercid"), rs.getString("content"), rs.getLong("timestamp"))); } rs.close(); ps.close(); ps = con.prepareStatement("SELECT guildid FROM guilds"); rs = ps.executeQuery(); while (rs.next()) { WorldGuildService.getInstance().addLoadedGuild(new MapleGuild(rs.getInt("guildid"), replies)); } rs.close(); ps.close(); } catch (SQLException se) { log.error(new StringBuilder().append("[MapleGuild] 从数据库中加载家族信息出错.").append(se).toString()); } } public static void loadAll(Object toNotify) { Map replies = new LinkedHashMap(); try { Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("SELECT * FROM bbs_replies"); ResultSet rs = ps.executeQuery(); while (rs.next()) { int tID = rs.getInt("threadid"); Map reply = (Map) replies.get(Integer.valueOf(tID)); if (reply == null) { reply = new HashMap(); replies.put(tID, reply); } reply.put(reply.size(), new MapleBBSReply(reply.size(), rs.getInt("postercid"), rs.getString("content"), rs.getLong("timestamp"))); } rs.close(); ps.close(); boolean cont = false; ps = con.prepareStatement("SELECT guildid FROM guilds"); rs = ps.executeQuery(); while (rs.next()) { GuildLoad.QueueGuildForLoad(rs.getInt("guildid"), replies); cont = true; } rs.close(); ps.close(); if (!cont) { return; } } catch (SQLException se) { log.error(new StringBuilder().append("[MapleGuild] 从数据库中加载家族信息出错.").append(se).toString()); } AtomicInteger FinishedThreads = new AtomicInteger(0); GuildLoad.Execute(toNotify); synchronized (toNotify) { try { toNotify.wait(); } catch (InterruptedException ex) { ex.printStackTrace(); } } while (FinishedThreads.incrementAndGet() != 6) { synchronized (toNotify) { try { toNotify.wait(); } catch (InterruptedException ex) { ex.printStackTrace(); } } } } public final void writeToDB(boolean bDisband) { int ourId; try { Connection con = DatabaseConnection.getConnection(); if (!bDisband) { StringBuilder buf = new StringBuilder("UPDATE guilds SET GP = ?, logo = ?, logoColor = ?, logoBG = ?, logoBGColor = ?, "); for (int i = 1; i < 6; i++) { buf.append("rank").append(i).append("title = ?, "); } buf.append("capacity = ?, notice = ?, alliance = ?, leader = ? WHERE guildid = ?"); PreparedStatement ps = con.prepareStatement(buf.toString()); ps.setInt(1, this.gp); ps.setInt(2, this.logo); ps.setInt(3, this.logoColor); ps.setInt(4, this.logoBG); ps.setInt(5, this.logoBGColor); ps.setString(6, this.rankTitles[0]); ps.setString(7, this.rankTitles[1]); ps.setString(8, this.rankTitles[2]); ps.setString(9, this.rankTitles[3]); ps.setString(10, this.rankTitles[4]); ps.setInt(11, this.capacity); ps.setString(12, this.notice); ps.setInt(13, this.allianceid); ps.setInt(14, this.leader); ps.setInt(15, this.id); ps.executeUpdate(); ps.close(); if (this.changed) { ps = con.prepareStatement("DELETE FROM bbs_threads WHERE guildid = ?"); ps.setInt(1, this.id); ps.execute(); ps.close(); ps = con.prepareStatement("DELETE FROM bbs_replies WHERE guildid = ?"); ps.setInt(1, this.id); ps.execute(); ps.close(); try (PreparedStatement pse = con.prepareStatement("INSERT INTO bbs_replies (`threadid`, `postercid`, `timestamp`, `content`, `guildid`) VALUES (?, ?, ?, ?, ?)")) { ps = con.prepareStatement("INSERT INTO bbs_threads(`postercid`, `name`, `timestamp`, `icon`, `startpost`, `guildid`, `localthreadid`) VALUES(?, ?, ?, ?, ?, ?, ?)", 1); ps.setInt(6, this.id); for (MapleBBSThread bb : this.bbs.values()) { ps.setInt(1, bb.ownerID); ps.setString(2, bb.name); ps.setLong(3, bb.timestamp); ps.setInt(4, bb.icon); ps.setString(5, bb.text); ps.setInt(7, bb.localthreadID); ps.execute(); try (ResultSet rs = ps.getGeneratedKeys()) { if (!rs.next()) { rs.close(); continue; } ourId = rs.getInt(1); } pse.setInt(5, this.id); for (MapleBBSReply r : bb.replies.values()) { pse.setInt(1, ourId); pse.setInt(2, r.ownerID); pse.setLong(3, r.timestamp); pse.setString(4, r.content); pse.addBatch(); } } pse.executeBatch(); pse.close(); } ps.close(); } this.changed = false; } else { PreparedStatement ps = con.prepareStatement("DELETE FROM bbs_threads WHERE guildid = ?"); ps.setInt(1, this.id); ps.execute(); ps.close(); ps = con.prepareStatement("DELETE FROM bbs_replies WHERE guildid = ?"); ps.setInt(1, this.id); ps.execute(); ps.close(); ps = con.prepareStatement("DELETE FROM guilds WHERE guildid = ?"); ps.setInt(1, this.id); ps.executeUpdate(); ps.close(); broadcast(GuildPacket.guildDisband(this.id)); } } catch (SQLException se) { log.error(new StringBuilder().append("[MapleGuild] 保存家族信息出错.").append(se).toString()); } } public int getId() { return this.id; } public int getLeaderId() { return this.leader; } public MapleCharacter getLeader(MapleClient c) { return c.getChannelServer().getPlayerStorage().getCharacterById(this.leader); } public int getGP() { return this.gp; } public int getLogo() { return this.logo; } public void setLogo(int l) { this.logo = l; } public int getLogoColor() { return this.logoColor; } public void setLogoColor(int c) { this.logoColor = c; } public int getLogoBG() { return this.logoBG; } public void setLogoBG(int bg) { this.logoBG = bg; } public int getLogoBGColor() { return this.logoBGColor; } public void setLogoBGColor(int c) { this.logoBGColor = c; } public String getNotice() { if (this.notice == null) { return ""; } return this.notice; } public String getName() { return this.name; } public int getCapacity() { return this.capacity; } public int getSignature() { return this.signature; } public void broadcast(byte[] packet) { broadcast(packet, -1, BCOp.NONE); } public void broadcast(byte[] packet, int exception) { broadcast(packet, exception, BCOp.NONE); } // multi-purpose function that reaches every member of guild (except the character with exceptionId) in all channels with as little access to rmi as possible public void broadcast(byte[] packet, int exceptionId, BCOp bcop) { lock.writeLock().lock(); try { buildNotifications(); } finally { lock.writeLock().unlock(); } lock.readLock().lock(); try { for (MapleGuildCharacter mgc : this.members) { if (bcop == BCOp.DISBAND) { if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(mgc.getId(), 0, 5, 0, 5); } else { setOfflineGuildStatus(0, (byte) 5, 0, (byte) 5, mgc.getId()); } } else if (mgc.isOnline() && (mgc.getId() != exceptionId)) { if (bcop == BCOp.EMBELMCHANGE) { WorldGuildService.getInstance().changeEmblem(this.id, mgc.getId(), this); } else { WorldBroadcastService.getInstance().sendGuildPacket(mgc.getId(), packet, exceptionId, this.id); } } } } finally { lock.readLock().unlock(); } } private void buildNotifications() { if (!this.bDirty) { return; } List mem = new LinkedList(); for (MapleGuildCharacter mgc : this.members) { if (!mgc.isOnline()) { continue; } if ((mem.contains(mgc.getId())) || (mgc.getGuildId() != this.id)) { this.members.remove(mgc); continue; } mem.add(mgc.getId()); } this.bDirty = false; } public void setOnline(int cid, boolean online, int channel) { boolean bBroadcast = true; for (MapleGuildCharacter mgc : this.members) { if ((mgc.getGuildId() == this.id) && (mgc.getId() == cid)) { if (mgc.isOnline() == online) { bBroadcast = false; } mgc.setOnline(online); mgc.setChannel((byte) channel); break; } } if (bBroadcast) { broadcast(GuildPacket.guildMemberOnline(this.id, cid, online), cid); } this.bDirty = true; this.init = true; } public void guildChat(String name, int cid, String msg) { broadcast(MaplePacketCreator.multiChat(name, msg, 2), cid); } public void allianceChat(String name, int cid, String msg) { broadcast(MaplePacketCreator.multiChat(name, msg, 3), cid); } public String getRankTitle(int rank) { return this.rankTitles[(rank - 1)]; } public int getAllianceId() { return this.allianceid; } public int getInvitedId() { return this.invitedid; } public void setInvitedId(int iid) { this.invitedid = iid; } public void setAllianceId(int a) { this.allianceid = a; try { try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE guilds SET alliance = ? WHERE guildid = ?")) { ps.setInt(1, a); ps.setInt(2, this.id); ps.execute(); ps.close(); } } catch (SQLException e) { log.error(new StringBuilder().append("[MapleGuild] 保存家族联盟信息出错.").append(e).toString()); } } public static int createGuild(int leaderId, String name) { if (name.length() > 12) { return 0; } try { Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("SELECT guildid FROM guilds WHERE name = ?"); ps.setString(1, name); ResultSet rs = ps.executeQuery(); if (rs.first()) { rs.close(); ps.close(); return 0; } ps.close(); rs.close(); ps = con.prepareStatement("INSERT INTO guilds (`leader`, `name`, `signature`, `alliance`) VALUES (?, ?, ?, 0)", 1); ps.setInt(1, leaderId); ps.setString(2, name); ps.setInt(3, (int) (System.currentTimeMillis() / 1000L)); ps.executeUpdate(); rs = ps.getGeneratedKeys(); int ret = 0; if (rs.next()) { ret = rs.getInt(1); } rs.close(); ps.close(); return ret; } catch (SQLException se) { log.error(new StringBuilder().append("[MapleGuild] 创建家族信息出错.").append(se).toString()); } return 0; } public int addGuildMember(MapleGuildCharacter mgc) { this.lock.writeLock().lock(); try { if (this.members.size() >= this.capacity) { int i = 0; return i; } for (int i = this.members.size() - 1; i >= 0; i--) { if ((((MapleGuildCharacter) this.members.get(i)).getGuildRank() < 5) || (((MapleGuildCharacter) this.members.get(i)).getName().compareTo(mgc.getName()) < 0)) { this.members.add(i + 1, mgc); this.bDirty = true; break; } } } finally { this.lock.writeLock().unlock(); } gainGP(500, true, mgc.getId()); setGuildQuest(false, MapleCharacter.getCharacterById(mgc.getId())); broadcast(GuildPacket.newGuildMember(mgc)); return 1; } public final int addGuildJoinMember(final MapleGuildCharacter mgc) { lock.writeLock().lock(); try { if (members.size() >= capacity) { return 0; } } finally { lock.writeLock().unlock(); } setGuildQuest(true, MapleCharacter.getCharacterById(mgc.getId())); broadcast(GuildPacket.newGuildJoinMember(mgc)); return 1; } public final int removeGuildJoinMember(final int cid) { setGuildQuest(false, MapleCharacter.getCharacterById(cid)); broadcast(GuildPacket.removeGuildJoin(cid)); return 1; } public void leaveGuild(MapleGuildCharacter mgc) { this.lock.writeLock().lock(); try { for (MapleGuildCharacter mgcc : this.members) { if (mgcc.getId() == mgc.getId()) { broadcast(GuildPacket.memberLeft(mgcc, false)); this.bDirty = true; gainGP(mgcc.getGuildContribution() > 0 ? -mgcc.getGuildContribution() : -50); this.members.remove(mgcc); if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(mgcc.getId(), 0, 5, 0, 5); break; } setOfflineGuildStatus(0, (byte) 5, 0, (byte) 5, mgcc.getId()); break; } } } finally { this.lock.writeLock().unlock(); } } public void expelMember(MapleGuildCharacter initiator, String name, int chrId) { this.lock.writeLock().lock(); try { for (MapleGuildCharacter mgc : this.members) { if ((mgc.getId() == chrId) && (initiator.getGuildRank() < mgc.getGuildRank())) { broadcast(GuildPacket.memberLeft(mgc, true)); this.bDirty = true; gainGP(mgc.getGuildContribution() > 0 ? -mgc.getGuildContribution() : -50); if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(chrId, 0, 5, 0, 5); } else { MapleCharacterUtil.sendNote(mgc.getName(), initiator.getName(), "被家族除名了。", 0); setOfflineGuildStatus(0, (byte) 5, 0, (byte) 5, chrId); } this.members.remove(mgc); break; } } } finally { this.lock.writeLock().unlock(); } } public void changeARank() { changeARank(false); } public void changeARank(boolean leader) { if (this.allianceid <= 0) { return; } for (MapleGuildCharacter mgc : this.members) { byte newRank = 3; if (this.leader == mgc.getId()) { newRank = (byte) (leader ? 1 : 2); } if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(mgc.getId(), this.id, mgc.getGuildRank(), mgc.getGuildContribution(), newRank); } else { setOfflineGuildStatus(this.id, mgc.getGuildRank(), mgc.getGuildContribution(), newRank, mgc.getId()); } mgc.setAllianceRank(newRank); } } public void changeARank(int newRank) { if (this.allianceid <= 0) { return; } for (MapleGuildCharacter mgc : this.members) { if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(mgc.getId(), this.id, mgc.getGuildRank(), mgc.getGuildContribution(), newRank); } else { setOfflineGuildStatus(this.id, mgc.getGuildRank(), mgc.getGuildContribution(), (byte) newRank, mgc.getId()); } mgc.setAllianceRank((byte) newRank); } } public boolean changeARank(int chrId, int newRank) { if (this.allianceid <= 0) { return false; } for (MapleGuildCharacter mgc : this.members) { if (chrId == mgc.getId()) { if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(chrId, this.id, mgc.getGuildRank(), mgc.getGuildContribution(), newRank); } else { setOfflineGuildStatus(this.id, mgc.getGuildRank(), mgc.getGuildContribution(), (byte) newRank, chrId); } mgc.setAllianceRank((byte) newRank); return true; } } return false; } public void changeGuildLeader(int chrId) { if ((changeRank(chrId, 1)) && (changeRank(this.leader, 2))) { if (this.allianceid > 0) { int aRank = getMGC(this.leader).getAllianceRank(); if (aRank == 1) { } else { changeARank(chrId, aRank); } changeARank(this.leader, 3); } broadcast(GuildPacket.guildLeaderChanged(this.id, this.leader, chrId, this.allianceid)); this.leader = chrId; try { try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE guilds SET leader = ? WHERE guildid = ?")) { ps.setInt(1, chrId); ps.setInt(2, this.id); ps.execute(); ps.close(); } } catch (SQLException e) { log.error(new StringBuilder().append("[MapleGuild] Saving leaderid ERROR.").append(e).toString()); } } } public boolean changeRank(int chrId, int newRank) { for (MapleGuildCharacter mgc : this.members) { if (chrId == mgc.getId()) { if (mgc.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(chrId, this.id, newRank, mgc.getGuildContribution(), mgc.getAllianceRank()); } else { setOfflineGuildStatus(this.id, (byte) newRank, mgc.getGuildContribution(), mgc.getAllianceRank(), chrId); } mgc.setGuildRank((byte) newRank); broadcast(GuildPacket.changeRank(mgc)); return true; } } return false; } public void setGuildNotice(String notice) { this.notice = notice; broadcast(GuildPacket.guildNotice(this.id, notice)); } public void memberLevelJobUpdate(MapleGuildCharacter mgc) { for (MapleGuildCharacter member : this.members) { if (member.getId() == mgc.getId()) { int old_level = member.getLevel(); int old_job = member.getJobId(); member.setJobId(mgc.getJobId()); member.setLevel((short) mgc.getLevel()); if (mgc.getLevel() > old_level) { gainGP((mgc.getLevel() - old_level) * mgc.getLevel(), false, mgc.getId()); } if (old_level != mgc.getLevel()) { broadcast(MaplePacketCreator.sendLevelup(false, mgc.getLevel(), mgc.getName()), mgc.getId()); } if (old_job != mgc.getJobId()) { broadcast(MaplePacketCreator.sendJobup(false, mgc.getJobId(), mgc.getName()), mgc.getId()); } broadcast(GuildPacket.guildMemberLevelJobUpdate(mgc)); if (this.allianceid <= 0) { break; } break; } } } public void changeRankTitle(String[] ranks) { for (int i = 0; i < 5; i++) { this.rankTitles[i] = ranks[i]; } broadcast(GuildPacket.rankTitleChange(this.id, ranks)); } public void disbandGuild() { writeToDB(true); broadcast(null, -1, BCOp.DISBAND); } public void setGuildEmblem(short bg, byte bgcolor, short logo, byte logocolor) { this.logoBG = bg; this.logoBGColor = bgcolor; this.logo = logo; this.logoColor = logocolor; broadcast(null, -1, BCOp.EMBELMCHANGE); try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE guilds SET logo = ?, logoColor = ?, logoBG = ?, logoBGColor = ? WHERE guildid = ?")) { ps.setInt(1, logo); ps.setInt(2, this.logoColor); ps.setInt(3, this.logoBG); ps.setInt(4, this.logoBGColor); ps.setInt(5, this.id); ps.execute(); ps.close(); } catch (SQLException e) { log.error(new StringBuilder().append("[MapleGuild] Saving guild logo / BG colo ERROR.").append(e).toString()); } } public MapleGuildCharacter getMGC(int cid) { for (MapleGuildCharacter mgc : this.members) { if (mgc.getId() == cid) { return mgc; } } return null; } public boolean increaseCapacity(boolean trueMax) { if (this.capacity < (trueMax ? 200 : 100)) { if (this.capacity + 5 <= (trueMax ? 200 : 100)); } else { return false; } if ((trueMax) && (this.gp < 25000)) { return false; } if ((trueMax) && (this.gp - 25000 < GameConstants.getGuildExpNeededForLevel(getLevel() - 1))) { return false; } this.capacity += 5; broadcast(GuildPacket.guildCapacityChange(this.id, this.capacity)); try { try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE guilds SET capacity = ? WHERE guildid = ?")) { ps.setInt(1, this.capacity); ps.setInt(2, this.id); ps.execute(); ps.close(); } } catch (SQLException e) { log.error(new StringBuilder().append("[MapleGuild] Saving guild capacity ERROR.").append(e).toString()); } return true; } public void gainGP(int amount) { gainGP(amount, true, -1); } public void gainGP(int amount, boolean broadcast) { gainGP(amount, broadcast, -1); } public void gainGP(int amount, boolean broadcast, int chrId) { if (amount == 0) { return; } if (amount + this.gp < 0) { amount = -this.gp; } if ((chrId > 0) && (amount > 0)) { MapleGuildCharacter mg = getMGC(chrId); if (mg != null) { mg.setGuildContribution(mg.getGuildContribution() + amount); if (mg.isOnline()) { WorldGuildService.getInstance().setGuildAndRank(chrId, this.id, mg.getGuildRank(), mg.getGuildContribution(), mg.getAllianceRank()); } else { setOfflineGuildStatus(this.id, mg.getGuildRank(), mg.getGuildContribution(), mg.getAllianceRank(), chrId); } broadcast(GuildPacket.guildContribution(this.id, chrId, mg.getGuildContribution())); } } this.gp += amount; this.level = calculateLevel(); broadcast(GuildPacket.updateGP(this.id, this.gp, this.level)); } public int getLevel() { return this.level; } public final int calculateLevel() { for (int i = 1; i < 10; i++) { if (this.gp < GameConstants.getGuildExpNeededForLevel(i)) { return i; } } return 10; } public void addMemberData(MaplePacketLittleEndianWriter mplew) { List<MapleGuildCharacter> players = new ArrayList(); for (MapleGuildCharacter mgc : this.members) { if (mgc.getId() == this.leader) { players.add(mgc); } } for (MapleGuildCharacter mgc : this.members) { if (mgc.getId() != this.leader) { players.add(mgc); } } if (players.size() != this.members.size()) { FileoutputUtil.log(new StringBuilder().append("家族成员信息加载错误 - 实际加载: ").append(players.size()).append(" 应当加载: ").append(this.members.size()).toString()); } mplew.writeShort(players.size()); for (MapleGuildCharacter mgc : players) { mplew.writeInt(mgc.getId()); } for (MapleGuildCharacter mgc : players) { mplew.writeAsciiString(mgc.getName(), 13); mplew.writeInt(mgc.getJobId()); mplew.writeInt(mgc.getLevel()); mplew.writeInt(mgc.getGuildRank()); mplew.writeInt(mgc.isOnline() ? 1 : 0); mplew.writeInt(mgc.getAllianceRank()); mplew.writeInt(mgc.getGuildContribution()); mplew.writeInt(10); //v117 可能是GP+IGP mplew.writeInt(7); //v117 IGP mplew.writeLong(PacketHelper.getTime(System.currentTimeMillis())); //v117 } } public static MapleGuildResponse sendInvite(MapleClient c, String targetName) { MapleCharacter mc = c.getChannelServer().getPlayerStorage().getCharacterByName(targetName); if (mc == null) { return MapleGuildResponse.NOT_IN_CHANNEL; } if (mc.getGuildId() > 0) { return MapleGuildResponse.ALREADY_IN_GUILD; } mc.getClient().getSession().write(GuildPacket.guildInvite(c.getPlayer().getGuildId(), c.getPlayer().getName(), c.getPlayer().getLevel(), c.getPlayer().getJob())); return null; } public Collection<MapleGuildCharacter> getMembers() { return Collections.unmodifiableCollection(this.members); } public boolean isInit() { return this.init; } public List<MapleBBSThread> getBBS() { List ret = new ArrayList(this.bbs.values()); Collections.sort(ret, new MapleBBSThread.ThreadComparator()); return ret; } public int addBBSThread(String title, String text, int icon, boolean bNotice, int posterID) { int add = this.bbs.get(0) == null ? 1 : 0; this.changed = true; int ret = bNotice ? 0 : Math.max(1, this.bbs.size() + add); this.bbs.put(ret, new MapleBBSThread(ret, title, text, System.currentTimeMillis(), this.id, posterID, icon)); return ret; } public void editBBSThread(int localthreadid, String title, String text, int icon, int posterID, int guildRank) { MapleBBSThread thread = (MapleBBSThread) this.bbs.get(Integer.valueOf(localthreadid)); if ((thread != null) && ((thread.ownerID == posterID) || (guildRank <= 2))) { this.changed = true; this.bbs.put(localthreadid, new MapleBBSThread(localthreadid, title, text, System.currentTimeMillis(), this.id, thread.ownerID, icon)); } } public void deleteBBSThread(int localthreadid, int posterID, int guildRank) { MapleBBSThread thread = (MapleBBSThread) this.bbs.get(Integer.valueOf(localthreadid)); if ((thread != null) && ((thread.ownerID == posterID) || (guildRank <= 2))) { this.changed = true; this.bbs.remove(localthreadid); } } public void addBBSReply(int localthreadid, String text, int posterID) { MapleBBSThread thread = (MapleBBSThread) this.bbs.get(Integer.valueOf(localthreadid)); if (thread != null) { this.changed = true; thread.replies.put(thread.replies.size(), new MapleBBSReply(thread.replies.size(), posterID, text, System.currentTimeMillis())); } } public void deleteBBSReply(int localthreadid, int replyid, int posterID, int guildRank) { MapleBBSThread thread = (MapleBBSThread) this.bbs.get(Integer.valueOf(localthreadid)); if (thread != null) { MapleBBSReply reply = (MapleBBSReply) thread.replies.get(Integer.valueOf(replyid)); if ((reply != null) && ((reply.ownerID == posterID) || (guildRank <= 2))) { this.changed = true; thread.replies.remove(replyid); } } } public static void setOfflineGuildStatus(int guildid, byte guildrank, int contribution, byte alliancerank, int cid) { try { try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE characters SET guildid = ?, guildrank = ?, guildContribution = ?, alliancerank = ? WHERE id = ?")) { ps.setInt(1, guildid); ps.setInt(2, guildrank); ps.setInt(3, contribution); ps.setInt(4, alliancerank); ps.setInt(5, cid); ps.executeUpdate(); ps.close(); } } catch (SQLException se) { FileoutputUtil.log(new StringBuilder().append("SQLException: ").append(se.getLocalizedMessage()).toString()); } } public final void addMemberForm(final MaplePacketLittleEndianWriter mplew) { //mplew.write(members.size()); mplew.writeShort(joinList.size()); for (int cid : getJoinList()) { mplew.writeInt(cid); } for (int cid : getJoinList()) { MapleCharacter chr = MapleCharacter.getCharacterById(cid); if (chr != null) { chr.setGuildId(id); memberInfo(mplew, chr.getMGC()); chr.setGuildId(0); } } } private void memberInfo(final MaplePacketLittleEndianWriter mplew, MapleGuildCharacter mgc) { mplew.writeAsciiString(mgc.getName(), 13); mplew.writeInt(mgc.getJobId()); //-1 = ?? mplew.writeInt(mgc.getLevel()); //-1 = ?? mplew.writeInt(mgc.getGuildRank()); mplew.writeInt(mgc.isOnline() ? 1 : 0); mplew.writeInt(mgc.getAllianceRank()); mplew.writeInt(mgc.getGuildContribution()); mplew.writeInt(0); //v117 可能是GP+IGP mplew.writeInt(0); //v117 IGP mplew.writeLong(PacketHelper.getTime(System.currentTimeMillis())); //v117 } public static List<MapleGuild> searchGuild(String keyWord) { List<MapleGuild> guilds = new ArrayList<>(); for (MapleGuild guild : getAllGuilds()) { if (guild.getName().contains(keyWord) || guild.getMGC(guild.getLeaderId()).getName().contains(keyWord)) { guilds.add(guild); } } return guilds; } public static List<MapleGuild> searchGuild(int[] keyWords) { List<MapleGuild> guilds = new ArrayList<>(); for (MapleGuild guild : getAllGuilds()) { int a = guild.getMembers().size(); if (keyWords[0] <= guild.getLevel() && guild.getLevel() <= keyWords[1] && keyWords[2] <= guild.getMembers().size() && guild.getMembers().size() <= keyWords[3] && keyWords[4] <= guild.getAverageLevel() && guild.getMembers().size() <= keyWords[5]) { guilds.add(guild); } } return guilds; } public static List<MapleGuild> getAllGuilds() { List<MapleGuild> guilds = new ArrayList<>(); Connection con = DatabaseConnection.getConnection(); try { try (PreparedStatement ps = con.prepareStatement("SELECT * FROM `guilds`")) { ResultSet rs = ps.executeQuery(); while (rs.next()) { guilds.add(WorldGuildService.getInstance().getGuild(rs.getInt("guildid"))); } rs.close(); ps.close(); } } catch (SQLException se) { FileoutputUtil.log("SQLException: " + se.getLocalizedMessage()); } return guilds; } public final int getAverageLevel() { int totalLevel = 0; for (MapleGuildCharacter mgc : members) { totalLevel += mgc.getLevel(); } return totalLevel / members.size(); } public final void setGuildQuest(boolean add, MapleCharacter chr) { if (add) { addJoinList(chr.getId()); } else { removeJoinList(chr.getId()); } // chr.updateInfoQuest(GameConstants.申请公会名, add ? "name=" + name : ""); // chr.updateInfoQuest(GameConstants.申请公ID, add ? "GuildID=" + id : ""); } public final void addJoinList(int cid) { joinList.add(cid); } public final void removeJoinList(int cid) { Iterator<Integer> itr = joinList.iterator(); while (itr.hasNext()) { if (cid == itr.next()) { itr.remove(); } } } public static String getJoinGuildName(int cid) { MapleCharacter chr = MapleCharacter.getCharacterById(cid); String questInfo = chr.getInfoQuest(GameConstants.申请公会名); if (questInfo.split("=").length > 1) { return questInfo.split("=")[1]; } return null; } public static int getJoinGuildId(int cid) { MapleCharacter chr = MapleCharacter.getCharacterById(cid); String questInfo = chr.getInfoQuest(GameConstants.申请公ID); if (questInfo.split("=").length > 1) { return Integer.valueOf(questInfo.split("=")[1]); } return -1; } public final List<Integer> getJoinList() { return joinList; } private static enum BCOp { NONE, DISBAND, EMBELMCHANGE; } }