Movement packets are used to update player and mob (monster) movements on the map. There are multiple packets with varying structure that accomplish this. Each of these packets contain the same structure for "movement fragments" within them. These movement fragments illustrate what the player/mob was doing during that time segment. Each movement packet illustrates what the player/mob was doing over a period of a half a second. The server is tasked with reading these packets and distributing the movement information to clients whom are on the same map (also must be on the same channel and map).
Each client is tasked with sending packet updates to the server for the player it manages. The movement packet is parsed by the server and reconstructed into another (similar) packet containing the movement fragments from the original packet and is then sent to other clients on the same map. These movement fragments are then played pack as "ghosts" so to speak to visualize other players on the same map.
Mob movement is very similar to player movement, however additional information about the mob are also included in each packet. Only clients that control the monster are allowed to transmit movement updates for the monster. Clients are asked by the server to move various monsters in advance. Once tasked with monster movement that client is under control of the monsters every move. The controlling client for each monster sends movement packets for each monster it controls. Each monster movement received by the server and then distributed to all the players whom are on the same map.
There are 5 types of movement fragments. Each of these fragments have a different internal structure and purpose. The 5 movement fragment types are:
- Absolute Movement
- Jump Down Movement
- Relative Movement
- Instant Movement
- Equipment Movement
Absolute movement is the most commonly used movement fragment as it is used for basic movement such as walking along a foothold and moving the air. Relative movement is another commonly used fragment as it shows the entities jumping. Instant movement is used for teleportation and skills that move the character.
To reduce the amount of data transferred to and from the server, optimization is performed by the client to eliminate repeated/unnecessary packets. For example if the entity is not moving, movement fragments showing the players same un-moved location are removed. If the entity did not move since the last movement packet was sent, no movement packet will be sent. Additionally, fragments that can be reconstructed using the previous fragments velocity are left out. Moving in a straight line is a good example of this, where the player does not change speed. Typically a single packet will be sent to mark the players starting position with a duration that stretches the entire 500 milliseconds. Jumping is another occasion that optimization is performed as various fragments can be implied given the previous segments position and velocity. Instead of using absolute movement fragments to illustrate every frame of the jump, only a couple fragments are used to illustrate the same effect.
Genuine client verification
Part of the packet is allocated to verify the integrity of the client. For example, the first 5 bytes and the last 18 bytes of the player movement packet are used to verify integrity of the client. This is done by generating bytes that have no noticeable pattern to the outside observer, however both the client and server understand the pattern and agree with the pattern it creates/receives. Most private servers do not check this operation. Private servers typically skip over this section and assume that the data is valid.
Since each movement update is sent out every 500 milliseconds, there is a hard minimum of a 500 millisecond delay (lag) for other clients to receive this information. Transfer rates introduce additional delays on top of the 500 millisecond delay. Transfer rate between originating client and the server introduces delay, computational time on the server creates additional delay and finally transfer rate between the server and the originating client introduces additional delay. Clients are built to handle this properly to a maximum extent of delay. When significant delay causes packets to miss deadlines causing movement replay to run out, the client estimates the most likely action by continuation of movement. However, at a certain point the client no longer attempts to estimate the position of the entity and locks its position until the movement packet is received.
There are nine different types of packets that involve movement. Eight of the Nine include movement fragments. These are:
- Client: Move player (0x26)
- Client: Move life (0x9D)
- Client: Move pet (0x8C)
- Client: Move summon (0x94)
- Server: Move player (0x8D)
- Server: Move monster (0xB2)
- Server: Move pet (0x81)
- Server: Move summon (0x88)
- Server: Move monster response (0xB3)
Move monster response is the only packet on the list that does not include movement fragments. Even though the packet does not contain packet fragments, it is important to keep on the list as it is a response from the server to the client that sent the movement report including additional information for about the monster in the response.
Movement fragmentation section
This section illustrates how to parse the movement fragments out of the section.
MovementFragmentation = [count:uint8][fragment:MovementFragment]*count
The first byte "count" is the amount of movement fragments in the packet. After count count amount of MovementFragments are listed. Movement packets have a structure based on their type. Parsing these movement fragments are listed below.
MovementFragment = [fragment_type:uint8][...fragment data...]
Each MovementFragment starts with a byte that determines which of the five movement types the following movement fragment is. The list shown below shows what values relate to which fragment types:
- AbsoluteMovement - 0, 5, 17
- RelativeMovement - 1, 2, 6, 12, 13, 16
- InstantMovement - 3, 4, 7, 8, 9, 14
- EquipMovement - 10
- JumpDownMovement - 11
Given the movement fragment type is known, the following method listed bellow will parse the given MovementFragment type.
On jumps duration is 0
Jump down movement:
Description of variable names:
- position_x and position_y: position of the character at the start of the movement
- velocity_x and velocity_y: velocity components of the character at the start of the movement
- unknown: Truly unknown. Potentially another source of genuine client verification. Does not seem to make a difference with private servers so far.
- state: (Stance) Number representing what the player looks like during the movement fragment. A list of these is written below
- duration: The duration of the movement fragment in milliseconds.
- foothold_id: The foothold the player is jumping off of.
- data: (equip data) unknown
State / Stance
This is a number that represents the stance of the player (what the player looks like). For entries that list "x / y" both numbers listed, x and y, relate to the same stance. The difference between the two is the direction of the stance. Left is odd (Left side), right is even (right side).
- 3 / 2: Walk
- 5 / 4: Standing
- 7 / 6: Jumping & Falling
- 9 / 8: Normal attack
- 11 / 10: Prone
- 13 / 12: Rope
- 15 / 14: Ladder