package handling.channel.handler;
import client.MapleCharacter;
import client.MapleJob;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import server.maps.AnimatedMapleMapObject;
import server.movement.*;
import tools.FileoutputUtil;
import tools.HexTool;
import tools.data.LittleEndianAccessor;
public class MovementParse {
// 1 = 玩家, 2 = 怪物, 3 = 寵物, 4 = 召喚獸, 5 = 龍神
public static List<LifeMovementFragment> parseMovement(final LittleEndianAccessor lea, final int kind) {
return parseMovement(lea, kind, null);
}
public static List<LifeMovementFragment> parseMovement(final LittleEndianAccessor lea, final int kind, MapleCharacter chr) {
final List<LifeMovementFragment> res = new ArrayList<>();
final byte numCommands = lea.readByte();
for (byte i = 0; i < numCommands; i++) {
final byte command = lea.readByte();
switch (command) {
case 0:
case 8:
case 15:
case 16:
case 18:
case 54:
case 63:
case 64:
case 65:
case 66:
case 68: {
final short xpos = (short) lea.readShort();
final short ypos = lea.readShort();
final short xwobble = lea.readShort();
final short ywobble = lea.readShort();
final short unk = lea.readShort();
short fh = 0;
if (command == 15 || command == 16) {
fh = lea.readShort();
}
short xoffset = 0;
short yoffset = 0;
if (command != 54 || command != 63 || command != 68) {
xoffset = lea.readShort();
yoffset = lea.readShort();
}
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final byte wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(xpos, ypos), duration, newstate, unk);
mov.setUnk(unk);
mov.setFh(fh);
mov.setPixelsPerSecond(new Point(xwobble, ywobble));
mov.setOffset(new Point(xoffset, yoffset));
mov.setWui(wui);
res.add(mov);
break;
}
case 1:
case 2:
case 17:
case 20:
case 21:
case 23:
case 59:
case 60:
case 61:
case 62: {
final short xwobble = lea.readShort();
final short ywobble = lea.readShort();
short fh = 0;
if (command == 20 || command == 21) {
fh = lea.readShort();
}
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final byte wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(0, 0), duration, newstate, fh);
mov.setPixelsPerSecond(new Point(xwobble, ywobble));
mov.setFh(fh);
mov.setWui(wui);
res.add(mov);
break;
}
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
case 38:
case 39:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 48:
case 49:
case 53:
case 55:
case 56:
case 58:
case 70: {
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final byte wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(0, 0), duration, newstate, 0);
mov.setWui(wui);
res.add(mov);
break;
}
case 3:
case 4:
case 5:
case 6:
case 7:
case 9:
case 10:
case 11:
case 13:
case 25:
case 26:
case 50:
case 51:
case 52:
case 57: {
final short xpos = (short) lea.readShort();
final short ypos = lea.readShort();
final short unk = lea.readShort();
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final byte wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(xpos, ypos), duration, newstate, unk);
mov.setUnk(unk);
mov.setWui(wui);
res.add(mov);
break;
}
case 14: {
final short xpos = 0;
final short ypos = 0;
final short xwobble = lea.readShort();
final short ywobble = lea.readShort();
final short fh = lea.readShort();
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final byte wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(xpos, ypos), duration, newstate, fh);
mov.setPixelsPerSecond(new Point(xwobble, ywobble));
mov.setFh(fh);
mov.setWui(wui);
res.add(mov);
break;
}
case 22: {
final short xpos = (short) lea.readShort();
final short ypos = lea.readShort();
final short xwobble = lea.readShort();
final short ywobble = lea.readShort();
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final byte wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(xpos, ypos), duration, newstate, 0);
mov.setPixelsPerSecond(new Point(xwobble, ywobble));
mov.setWui(wui);
res.add(mov);
break;
}
case 12: {
final byte newstate = 0;
final short duration = 0;
final int wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(0, 0), duration, newstate, 0);
mov.setWui(wui);
res.add(mov);
break;
}
default:
final byte newstate = lea.readByte();
final short duration = lea.readShort();
final int wui = lea.readByte();
final StaticLifeMovement mov = new StaticLifeMovement(command, new Point(0, 0), duration, newstate, 0);
mov.setWui(wui);
res.add(mov);
System.out.println("未知的移動類型: 0x" + HexTool.toString(command) + " - ( " + command + " )");
if (chr.isShowErr()) {
chr.showInfo("移動", true, "未知的移動類型: 0x" + HexTool.toString(command) + " - ( " + command + " )");
}
String moveMsg = "";
if (kind == 1) {
moveMsg = "玩家";
} else if (kind == 2) {
moveMsg = "怪物";
} else if (kind == 3) {
moveMsg = "寵物";
} else if (kind == 4) {
moveMsg = "召喚獸";
} else if (kind == 5) {
moveMsg = "龍";
} else if (kind == 6) {
moveMsg = "攻擊怪物";
}
FileoutputUtil.log(FileoutputUtil.Movement_Log, moveMsg + "(" + chr.getName() + ") 職業:" + MapleJob.getName(MapleJob.getById(chr.getJob())) + "(" + chr.getJob() + ") 未知移動封包 剩餘次數: " + (numCommands - res.size()) + " 移動類型: 0x" + HexTool.toString(command) + ", 封包: " + lea.toString(true));
return null;
}
if (kind == 6) {
if (chr.isShowErr()) {
chr.showInfo("移動", true, "攻擊怪物" + "(" + chr.getName() + ") 職業:" + MapleJob.getName(MapleJob.getById(chr.getJob())) + "移動類型: 0x" + HexTool.toString(command));
}
FileoutputUtil.log(FileoutputUtil.Movement_Log, "攻擊怪物" + "(" + chr.getName() + ") 職業:" + MapleJob.getName(MapleJob.getById(chr.getJob())) + "移動類型: 0x" + HexTool.toString(command) + ", 封包: " + lea.toString(true));
}
}
double skip = lea.readByte();
skip = Math.ceil(skip / 2.0D);
lea.skip((int) skip);
if (numCommands != res.size()) {
System.out.println("循環次數[" + numCommands + "]和實際上獲取的循環次數[" + res.size() + "]不符");
if (chr.isShowErr()) {
chr.showInfo("移動", true, "循環次數[" + numCommands + "]和實際上獲取的循環次數[" + res.size() + "]不符");
}
FileoutputUtil.log(FileoutputUtil.Movement_Log, "循環次數[" + numCommands + "]和實際上獲取的循環次數[" + res.size() + "]不符 " + "(" + chr.getName() + ") 職業:" + MapleJob.getName(MapleJob.getById(chr.getJob())) + "(" + chr.getJob() + "移動封包 剩餘次數: " + (numCommands - res.size()) + " 封包: " + lea.toString(true));
return null; // Probably hack
}
return res;
}
public static void updatePosition(final List<LifeMovementFragment> movement, final AnimatedMapleMapObject target, final int yoffset) {
if (movement == null) {
return;
}
for (final LifeMovementFragment move : movement) {
if (move instanceof LifeMovement) {
if (move instanceof StaticLifeMovement) {
final Point position = ((LifeMovement) move).getPosition();
position.y += yoffset;
target.setPosition(position);
}
target.setStance(((LifeMovement) move).getNewstate());
target.setNewFh(((LifeMovement) move).getNewFh());
}
}
}
}