package handling.channel.handler; import client.MapleCharacter; import java.awt.Point; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import server.maps.AnimatedMapleMapObject; import server.movement.AbsoluteLifeMovement; import server.movement.BounceMovement; import server.movement.ChangeEquipSpecialAwesome; import server.movement.LifeMovement; import server.movement.LifeMovementFragment; import server.movement.RelativeLifeMovement; import server.movement.TeleportMovement; import tools.FileoutputUtil; import tools.data.input.SeekableLittleEndianAccessor; public class MovementParse { private static final Logger log = Logger.getLogger(MovementParse.class); //1 = player, 2 = mob, 3 = pet, 4 = summon, 5 = dragon public static List<LifeMovementFragment> parseMovement(final SeekableLittleEndianAccessor lea, final int kind) { return parseMovement(lea, kind, null); } //来源于IDB的类型 public static List<LifeMovementFragment> parseMovement(SeekableLittleEndianAccessor lea, int kind, MapleCharacter chr) { final List<LifeMovementFragment> res = new ArrayList<>(); final byte numCommands = lea.readByte(); for (byte i = 0; i < numCommands; i++) { final int command = lea.readByte(); switch (command) { case -1: short xpos = lea.readShort(); short ypos = lea.readShort(); short unk = lea.readShort(); short fh = lea.readShort(); byte newstate = lea.readByte(); short duration = lea.readShort(); final BounceMovement bm = new BounceMovement(command, new Point(xpos, ypos), duration, newstate); bm.setFH(fh); bm.setUnk(unk); res.add(bm); break; case 0: // ok case 5: xpos = lea.readShort(); ypos = lea.readShort(); short xwobble = lea.readShort(); short ywobble = lea.readShort(); duration = lea.readShort(); newstate = lea.readByte(); short newfh=lea.readShort(); final AbsoluteLifeMovement alm = new AbsoluteLifeMovement(command, new Point(xpos, ypos), duration, newstate); alm.setPixelsPerSecond(new Point(xwobble, ywobble)); alm.setNewFH(newfh); res.add(alm); break; case 1: case 2: case 6: xwobble = lea.readShort(); ywobble = lea.readShort(); newstate = lea.readByte(); duration = lea.readShort(); final RelativeLifeMovement rlm = new RelativeLifeMovement(command, new Point(xwobble, ywobble), duration, newstate); res.add(rlm); break; case 3: case 4: case 7: xpos = lea.readShort(); ypos = lea.readShort(); xwobble = lea.readShort(); ywobble = lea.readShort(); newstate = lea.readByte(); final TeleportMovement tm = new TeleportMovement(command, new Point(xpos, ypos),0, newstate); tm.setPixelsPerSecond(new Point(xwobble, ywobble)); res.add(tm); break; case 8: res.add(new ChangeEquipSpecialAwesome(lea.readByte(),0)); break; default: FileoutputUtil.log(FileoutputUtil.Movement_Err, "未知移动封包:[" + command + "]" + "(" + chr.getName() + ") 职业:" + chr.getJobName() + "(" + chr.getJob() + "移动封包 剩余次数: " + (numCommands - res.size()) + " 封包: " + lea.toString(true)); break; } } if (numCommands != res.size()) { log.warn("循环次数[" + numCommands + "]和实际上获取的循环次数[" + res.size() + "]不符"); FileoutputUtil.log(FileoutputUtil.Movement_Err, "循环次数[" + numCommands + "]和实际上获取的循环次数[" + res.size() + "]不符 " + "(" + chr.getName() + ") 职业:" + chr.getJobName() + "(" + chr.getJob() + "移动封包 剩余次数: " + (numCommands - res.size()) + " 封包: " + lea.toString(true)); return null; } return res; } public static void updatePosition(List<LifeMovementFragment> movement, AnimatedMapleMapObject target, int yoffset) { if (movement == null) { return; } for (LifeMovementFragment move : movement) { if ((move instanceof LifeMovement)) { if ((move instanceof AbsoluteLifeMovement)) { Point position = ((LifeMovement) move).getPosition(); position.y += yoffset; target.setPosition(position); } target.setStance(((LifeMovement) move).getNewstate()); } } } }