/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
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 as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
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 net.server.handlers.channel;
import net.server.guild.MapleGuildResponse;
import net.server.guild.MapleGuild;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import tools.data.input.SeekableLittleEndianAccessor;
import java.util.Iterator;
import tools.MaplePacketCreator;
import tools.Output;
import client.MapleCharacter;
import net.server.Server;
public final class GuildOperationHandler extends AbstractMaplePacketHandler {
private boolean isGuildNameAcceptable(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 void respawnPlayer(MapleCharacter mc) {
mc.getMap().broadcastMessage(mc, MaplePacketCreator.removePlayerFromMap(mc.getId()), false);
mc.getMap().broadcastMessage(mc, MaplePacketCreator.spawnPlayerMapobject(mc), false);
}
private class Invited {
public String name;
public int gid;
public long expiration;
public Invited(String n, int id) {
name = n.toLowerCase();
gid = id;
expiration = System.currentTimeMillis() + 60 * 60 * 1000;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Invited)) {
return false;
}
Invited oth = (Invited) other;
return (gid == oth.gid && name.equals(oth));
}
@Override
public int hashCode() {
int hash = 3;
hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 83 * hash + this.gid;
return hash;
}
}
private java.util.List<Invited> invited = new java.util.LinkedList<Invited>();
private long nextPruneTime = System.currentTimeMillis() + 20 * 60 * 1000;
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
if (System.currentTimeMillis() >= nextPruneTime) {
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;
}
MapleCharacter mc = c.getPlayer();
byte type = slea.readByte();
switch (type) {
case 0x00:
// c.announce(MaplePacketCreator.showGuildInfo(mc));
break;
case 0x02:
if (mc.getGuildId() > 0 || mc.getMapId() != 200000301) {
c.getPlayer().dropMessage(1, "You cannot create a new Guild while in one.");
return;
}
if (mc.getMeso() < MapleGuild.CREATE_GUILD_COST) {
c.getPlayer().dropMessage(1, "You do not have enough mesos to create a Guild.");
return;
}
String guildName = slea.readMapleAsciiString();
if (!isGuildNameAcceptable(guildName)) {
c.getPlayer().dropMessage(1, "The Guild name you have chosen is not accepted.");
return;
}
int gid;
gid = Server.getInstance().createGuild(mc.getId(), guildName);
if (gid == 0) {
c.announce(MaplePacketCreator.genericGuildMessage((byte) 0x1c));
return;
}
mc.gainMeso(-MapleGuild.CREATE_GUILD_COST, true, false, true);
mc.setGuildId(gid);
mc.setGuildRank(1);
mc.saveGuildStatus();
c.announce(MaplePacketCreator.showGuildInfo(mc));
c.getPlayer().dropMessage(1, "You have successfully created a Guild.");
respawnPlayer(mc);
break;
case 0x05:
if (mc.getGuildId() <= 0 || mc.getGuildRank() > 2) {
return;
}
String name = slea.readMapleAsciiString();
MapleGuildResponse mgr = MapleGuild.sendInvite(c, name);
if (mgr != null) {
c.announce(mgr.getPacket());
} else {
Invited inv = new Invited(name, mc.getGuildId());
if (!invited.contains(inv)) {
invited.add(inv);
}
}
break;
case 0x06:
if (mc.getGuildId() > 0) {
Output.print("[GOH] " + mc.getName() + " attempted to join a guild when s/he is already in one.");
return;
}
gid = slea.readInt();
int cid = slea.readInt();
if (cid != mc.getId()) {
Output.print("[GOH] " + mc.getName() + " attempted to join a guild with a different character id.");
return;
}
name = mc.getName().toLowerCase();
Iterator<Invited> itr = invited.iterator();
boolean bOnList = false;
while (itr.hasNext()) {
Invited inv = itr.next();
if (gid == inv.gid && name.equals(inv.name)) {
bOnList = true;
itr.remove();
break;
}
}
if (!bOnList) {
Output.print("[GOH] " + mc.getName() + " is trying to join a guild that never invited him/her (or that the invitation has expired)");
return;
}
mc.setGuildId(gid); // joins the guild
mc.setGuildRank(5); // start at lowest rank
int s;
s = Server.getInstance().addGuildMember(mc.getMGC());
if (s == 0) {
c.getPlayer().dropMessage(1, "The Guild you are trying to join is already full.");
mc.setGuildId(0);
return;
}
c.announce(MaplePacketCreator.showGuildInfo(mc));
mc.saveGuildStatus(); // update database
respawnPlayer(mc);
break;
case 0x07:
cid = slea.readInt();
name = slea.readMapleAsciiString();
if (cid != mc.getId() || !name.equals(mc.getName()) || mc.getGuildId() <= 0) {
System.out.println("[hax] " + mc.getName() + " tried to quit guild under the name \"" + name + "\" and current guild id of " + mc.getGuildId() + ".");
return;
}
Server.getInstance().leaveGuild(mc.getMGC());
c.announce(MaplePacketCreator.showGuildInfo(null));
mc.setGuildId(0);
mc.saveGuildStatus();
respawnPlayer(mc);
break;
case 0x08:
cid = slea.readInt();
name = slea.readMapleAsciiString();
if (mc.getGuildRank() > 2 || mc.getGuildId() <= 0) {
System.out.println("[hax] " + mc.getName() + " is trying to expel without rank 1 or 2.");
return;
}
Server.getInstance().expelMember(mc.getMGC(), name, cid);
break;
case 0x0d:
if (mc.getGuildId() <= 0 || mc.getGuildRank() != 1) {
System.out.println("[hax] " + mc.getName() + " tried to change guild rank titles when s/he does not have permission.");
return;
}
String ranks[] = new String[5];
for (int i = 0; i < 5; i++) {
ranks[i] = slea.readMapleAsciiString();
}
Server.getInstance().changeRankTitle(mc.getGuildId(), ranks);
break;
case 0x0e:
cid = slea.readInt();
byte newRank = slea.readByte();
if (mc.getGuildRank() > 2 || (newRank <= 2 && mc.getGuildRank() != 1) || mc.getGuildId() <= 0) {
System.out.println("[hax] " + mc.getName() + " is trying to change rank outside of his/her permissions.");
return;
}
if (newRank <= 1 || newRank > 5) {
return;
}
Server.getInstance().changeRank(mc.getGuildId(), cid, newRank);
break;
case 0x0f:
if (mc.getGuildId() <= 0 || mc.getGuildRank() != 1 || mc.getMapId() != 200000301) {
System.out.println("[hax] " + mc.getName() + " tried to change guild emblem without being the guild leader.");
return;
}
if (mc.getMeso() < MapleGuild.CHANGE_EMBLEM_COST) {
c.announce(MaplePacketCreator.serverNotice(1, "You do not have enough mesos to create a Guild."));
return;
}
short bg = slea.readShort();
byte bgcolor = slea.readByte();
short logo = slea.readShort();
byte logocolor = slea.readByte();
Server.getInstance().setGuildEmblem(mc.getGuildId(), bg, bgcolor, logo, logocolor);
mc.gainMeso(-MapleGuild.CHANGE_EMBLEM_COST, true, false, true);
respawnPlayer(mc);
break;
case 0x10:
if (mc.getGuildId() <= 0 || mc.getGuildRank() > 2) {
System.out.println("[hax] " + mc.getName() + " tried to change guild notice while not in a guild.");
return;
}
String notice = slea.readMapleAsciiString();
if (notice.length() > 100) {
return;
}
Server.getInstance().setGuildNotice(mc.getGuildId(), notice);
break;
default:
System.out.println("Unhandled GUILD_OPERATION packet: \n" + slea.toString());
}
}
}