/* * This file is part of the OdinMS Maple Story Server Copyright (C) 2008 ~ 2010 * Patrick Huy <patrick.huy@frz.cc> Matthias Butz <matze@odinms.de> Jan * Christian Meyer <vimes@odinms.de> * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation. You may not use, modify or distribute this * program under any other version of the GNU Affero General Public License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package javastory.channel.handling; import java.rmi.RemoteException; import java.util.Iterator; import java.util.List; import com.google.common.collect.Lists; import javastory.channel.ChannelCharacter; import javastory.channel.ChannelClient; import javastory.channel.ChannelServer; import javastory.channel.Guild; import javastory.channel.client.MemberRank; import javastory.io.GamePacket; import javastory.io.PacketFormatException; import javastory.io.PacketReader; import javastory.tools.packets.ChannelPackets; import javastory.world.core.GuildOperationResponse; public class GuildHandler { public static void handleDenyGuildInvitation(final String from, final ChannelClient c) { final ChannelCharacter cfrom = ChannelServer.getPlayerStorage().getCharacterByName(from); if (cfrom != null) { cfrom.getClient().write(ChannelPackets.denyGuildInvitation(c.getPlayer().getName())); } } private static void handleCreateGuild(final ChannelCharacter player, final PacketReader reader, final ChannelClient c) throws PacketFormatException { // Create guild if (player.getGuildId() > 0 || player.getMapId() != 200000301) { player.sendNotice(1, "You cannot create a new Guild while in one."); return; } else if (player.getMeso() < 5000000) { player.sendNotice(1, "You do not have enough mesos to create a Guild."); return; } final String guildName = reader.readLengthPrefixedString(); if (!isGuildNameAcceptable(guildName)) { player.sendNotice(1, "The Guild name you have chosen is not accepted."); return; } int guildId; try { guildId = ChannelServer.getWorldInterface().createGuild(player.getId(), guildName); } catch (final RemoteException re) { System.err.println("RemoteException occurred" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); return; } if (guildId == 0) { c.write(ChannelPackets.genericGuildMessage((byte) 0x1c)); return; } player.gainMeso(-5000000, true, false, true); player.setGuildId(guildId); player.setGuildRank(MemberRank.MASTER); player.saveGuildStatus(); c.write(ChannelPackets.showGuildInfo(c, guildId)); player.sendNotice(1, "You have successfully created a Guild."); respawnPlayer(player); } private static void handleInviteToGuild(final ChannelCharacter player, final PacketReader reader, final ChannelClient c) throws PacketFormatException { // invitation if (player.getGuildId() <= 0 || !player.getGuildRank().isMaster()) { return; } final String name = reader.readLengthPrefixedString(); final GuildOperationResponse mgr = Guild.sendInvite(c, name); if (mgr != null) { final GamePacket packet = ChannelPackets.genericGuildMessage((byte) mgr.getValue()); c.write(packet); } else { final Invited inv = new Invited(name, player.getGuildId()); if (!invited.contains(inv)) { invited.add(inv); } } } private static boolean isGuildNameAcceptable(final String name) { if (name.length() < 3 || name.length() > 12) { return false; } for (int i = 0; i < name.length(); i++) { if (!Character.isLowerCase(name.charAt(i)) && !Character.isUpperCase(name.charAt(i))) { return false; } } return true; } private static void respawnPlayer(final ChannelCharacter mc) { mc.getMap().broadcastMessage(mc, ChannelPackets.removePlayerFromMap(mc.getId()), false); mc.getMap().broadcastMessage(mc, ChannelPackets.spawnPlayerMapObject(mc), false); } private static final class Invited { public String name; public int gid; public long expiration; public Invited(final String n, final int id) { this.name = n.toLowerCase(); this.gid = id; this.expiration = System.currentTimeMillis() + 3600000; } @Override public final boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } final Invited other = (Invited) obj; return this.gid == other.gid && this.name.equals(other.name); } @Override public int hashCode() { int hash = 7; hash = 13 * hash + (this.name != null ? this.name.hashCode() : 0); hash = 13 * hash + this.gid; return hash; } } private static final List<Invited> invited = Lists.newLinkedList(); private static long nextPruneTime = System.currentTimeMillis() + 20 * 60 * 1000; private static void handleAcceptGuildInvite(final ChannelCharacter player, final PacketReader reader, final ChannelClient c) throws PacketFormatException { // accepted guild invitation if (player.getGuildId() > 0) { return; } final int guildId = reader.readInt(); final int targetId = reader.readInt(); if (targetId != player.getId()) { return; } final String name = player.getName().toLowerCase(); final Iterator<Invited> itr = invited.iterator(); while (itr.hasNext()) { final Invited inv = itr.next(); if (guildId == inv.gid && name.equals(inv.name)) { player.setGuildId(guildId); player.setGuildRank(MemberRank.MEMBER_LOW); itr.remove(); boolean success = false; try { success = ChannelServer.getWorldInterface().addGuildMember(player.getGuildMembership()); } catch (final RemoteException e) { System.err.println("RemoteException occurred while attempting to add character to guild" + e); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); player.setGuildId(0); return; } if (!success) { player.sendNotice(1, "The Guild you are trying to join is already full."); player.setGuildId(0); return; } c.write(ChannelPackets.showGuildInfo(c, guildId)); player.saveGuildStatus(); respawnPlayer(player); return; } } } public static void handleGuildOperation(final PacketReader reader, final ChannelClient c) throws PacketFormatException { if (System.currentTimeMillis() >= nextPruneTime) { final Iterator<Invited> itr = invited.iterator(); Invited inv; while (itr.hasNext()) { inv = itr.next(); if (System.currentTimeMillis() >= inv.expiration) { itr.remove(); } } nextPruneTime = System.currentTimeMillis() + 20 * 60 * 1000; } final ChannelCharacter player = c.getPlayer(); String name; switch (reader.readByte()) { case 0x02: handleCreateGuild(player, reader, c); break; case 0x05: handleInviteToGuild(player, reader, c); break; case 0x06: handleAcceptGuildInvite(player, reader, c); break; case 0x07: // leaving int targetId = reader.readInt(); name = reader.readLengthPrefixedString(); if (targetId != player.getId() || !name.equals(player.getName()) || player.getGuildId() <= 0) { break; } try { ChannelServer.getWorldInterface().leaveGuild(player.getGuildMembership()); } catch (final RemoteException re) { System.err.println("RemoteException occurred while attempting to leave guild" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); break; } c.write(ChannelPackets.showNullGuildInfo()); player.setGuildId(0); player.saveGuildStatus(); respawnPlayer(player); break; case 0x08: // Expel targetId = reader.readInt(); name = reader.readLengthPrefixedString(); if (!player.getGuildRank().isMaster() || player.getGuildId() <= 0) { return; } try { ChannelServer.getWorldInterface().expelMember(player.getGuildMembership(), targetId); } catch (final RemoteException re) { System.err.println("RemoteException occurred while attempting to change rank" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); return; } break; case 0x0d: // handleGuildOperation rank titles change if (player.getGuildId() <= 0 || !player.getGuildRank().equals(MemberRank.MASTER)) { return; } final String ranks[] = new String[5]; for (int i = 0; i < 5; i++) { ranks[i] = reader.readLengthPrefixedString(); } try { ChannelServer.getWorldInterface().changeRankTitle(player.getGuildId(), ranks); } catch (final RemoteException re) { System.err.println("RemoteException occurred" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); return; } break; case 0x0e: // Rank change if (player.getGuildId() <= 0) { return; } targetId = reader.readInt(); final byte newRankNumber = reader.readByte(); final MemberRank newRank = MemberRank.fromNumber(newRankNumber); if (newRank == null) { return; } if (!player.getGuildRank().isMaster()) { return; } if (!player.getGuildRank().isSuperior(newRank)) { return; } try { ChannelServer.getWorldInterface().changeRank(player.getGuildId(), targetId, newRank); } catch (final RemoteException re) { System.err.println("RemoteException occurred while attempting to change rank" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); return; } break; case 0x0f: // guild emblem change if (player.getMapId() != 200000301) { return; } if (player.getGuildId() <= 0) { return; } if (!player.getGuildRank().equals(MemberRank.MASTER)) { return; } if (player.getMeso() < 15000000) { player.sendNotice(1, "You do not have enough mesos to create a Guild."); return; } final short bg = reader.readShort(); final byte bgcolor = reader.readByte(); final short logo = reader.readShort(); final byte logocolor = reader.readByte(); try { ChannelServer.getWorldInterface().setGuildEmblem(player.getGuildId(), bg, bgcolor, logo, logocolor); } catch (final RemoteException re) { System.err.println("RemoteException occurred" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); return; } player.gainMeso(-15000000, true, false, true); respawnPlayer(player); break; case 0x10: // guild notice change final String notice = reader.readLengthPrefixedString(); if (notice.length() > 100 || player.getGuildId() <= 0) { return; } if (!player.getGuildRank().isMaster()) { return; } try { ChannelServer.getWorldInterface().setGuildNotice(player.getGuildId(), notice); } catch (final RemoteException re) { System.err.println("RemoteException occurred" + re); player.sendNotice(5, "Unable to connect to the World Server. Please try again later."); return; } break; } } }