package handling.mina;
import client.MapleClient;
import handling.RecvPacketOpcode;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import server.ServerProperties;
import tools.FileoutputUtil;
import tools.HexTool;
import tools.MapleAESOFB;
import tools.StringUtil;
import tools.data.input.ByteArrayByteStream;
import tools.data.input.GenericLittleEndianAccessor;
public final class MaplePacketDecoder extends CumulativeProtocolDecoder {
public static final String DECODER_STATE_KEY = MaplePacketDecoder.class.getName() + ".STATE";
@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
DecoderState decoderState = (DecoderState) session.getAttribute(DECODER_STATE_KEY);
MapleClient client = (MapleClient) session.getAttribute("CLIENT");
if (decoderState.packetlength == -1) {
if (in.remaining() >= 4) {
int packetHeader = in.getInt(); // 另外一种方式,getShort() xor getShort()
decoderState.packetlength = MapleAESOFB.getPacketLength(packetHeader);
} else {
FileoutputUtil.log("没有足够的数据来解密封包.");
return false;
}
}
if (in.remaining() >= decoderState.packetlength) {
byte[] decryptedPacket = new byte[decoderState.packetlength];
in.get(decryptedPacket, 0, decoderState.packetlength);
decoderState.packetlength = -1;
client.getReceiveCrypto().crypt(decryptedPacket);
out.write(decryptedPacket);
if (ServerProperties.ShowPacket()) {
int packetLen = decryptedPacket.length;
int pHeader = readFirstByte(decryptedPacket);
boolean 记录 = true;
for (final RecvPacketOpcode recv : RecvPacketOpcode.values()) {
if (recv.getValue() == pHeader) {
if ( !ServerProperties.ShowPacket() ? RecvPacketOpcode.isTempHeader(recv) : RecvPacketOpcode.isSpamHeader(recv)) {//暂时记录怪物和角色移动
记录 = false;
}
break;
}
}
if (!记录) {
return true;
}
String pHeaderStr = Integer.toHexString(pHeader).toUpperCase();
pHeaderStr = StringUtil.getLeftPaddedStr(pHeaderStr, '0', 4);
String op = lookupSend(pHeader);
String Send = "[客户端发送] " + op + " [0x" + pHeaderStr + "] (" + packetLen + "字节) " + FileoutputUtil.CurrentReadable_Time() + "\r\n";
if (packetLen <= 6000) {
String SendTo = Send + HexTool.toString(decryptedPacket) + "\r\n" + HexTool.toStringFromAscii(decryptedPacket);
if (!ServerProperties.RecvPacket(op, pHeaderStr)) {
String SendTos = "\r\n时间:" + FileoutputUtil.CurrentReadable_Time() + " ";
FileoutputUtil.packetLog(FileoutputUtil.PacketLog, SendTo);
System.out.print(Send);
if ((op.equals("CLOSE_RANGE_ATTACK")) || (op.equals("RANGED_ATTACK")) || (op.equals("SUMMON_ATTACK")) || (op.equals("MAGIC_ATTACK"))) {
FileoutputUtil.packetLog(FileoutputUtil.AttackLog, SendTos + SendTo);
} else if (op.endsWith("PLAYER_INTERACTION")) {
FileoutputUtil.packetLog(FileoutputUtil.玩家互动封包, SendTos + SendTo);
} else if (op.equals("UNKNOWN")) {
FileoutputUtil.packetLog(FileoutputUtil.Packet_Unk, SendTos + SendTo);
}
}
} else {
FileoutputUtil.log(Send + HexTool.toString(new byte[]{decryptedPacket[0], decryptedPacket[1]}) + "...\r\n");
}
}
return true;
}
return false;
}
private String lookupSend(int val) {
for (RecvPacketOpcode op : RecvPacketOpcode.values()) {
if (op.getValue() == val) {
return op.name();
}
}
return "UNKNOWN";
}
private int readFirstByte(byte[] arr) {
return new GenericLittleEndianAccessor(new ByteArrayByteStream(arr)).readByte();
}
public static class DecoderState {
public int packetlength = -1;
}
}