- Joined
- Jul 30, 2008
- Messages
- 191
- Reaction score
- 36
Well I was browsing GZP even though they seem to think I'm going to release some files there or some crap... so I got banned as far as IRC and etc...
But not sure if this has been posted or not yet.. suppose it would help you guys out who are trying to develop a server.
So with all do credit to the poser at GZP(captiello).. it's in the code tags.
But not sure if this has been posted or not yet.. suppose it would help you guys out who are trying to develop a server.
So with all do credit to the poser at GZP(captiello).. it's in the code tags.
Code:
Flyff Packet Structure
short: 2byte
int: 4byte
float: 4byte
pstr: [(int)length][string]
Client's packet structure
These are packets sent by the client to the server
[(byte)0x5e][(int)unknown][(int)length][data][(int)s]
0x5e: starts every packet
unknown: the next 4 bytes should be skipped
length: length of the data field in bytes
data: commands/requests to the server
s: this field has to be saved in the charserver
For recieving the clients packets, you need to read the first 9 bytes(3 fields) of the packet, than determine the remaining bytes by the length field, and read them (its length+4 because length doesnt include the s field).
The data field's structure:
[(int)unknown][(int)0xffffffff][(int)command_id][command_data]
unknown: yet again. 4 bytes to be skipped
0xffffffff: this value is constant. allways -1
command_id: this integer determines what to do with the upcomeing data (if any)
command_data: this field's size is determined by the command_id (but it doesnt exceed the packet's length+4!).
Its usually uses the s field for data storage as well.
The client allways sends only 1 command per packet.
Server's packet structure
These are packets sent by the server to the client
[(byte)0x5e][(int)length][data]
0x5e: starts every packet
length: length of the data field in bytes
data: commands/answers to the client
This is basically the same as the clients structure above, without the unknown fields, and without the s field.
The data field's structure:
Loginserver and characterserver:
These servers only send 1 command per packet.
[(int)command_id][command_data]
command_id: determines what to do with the upcomeing data
command_data: size is determined by the command_id, same as above just note there is no s field.
Worldserver:
This server may send multiple commands per packet.
[(int)a][(int)character_id][(short)ncommands][commandfield]
a: this is usually 0xffffff00, except at the first packet sent by the worldserver, where its 0x0000ff00
character_id: the character's id wich is logged in on the client wich this packet is sent to.
ncommands: number of commands in the comand field
The command field's structure:
The command field is consist of ncommands number of commands with the following structure:
[(int)character_id][(short)command_id][command_data]
character_id: the character's id wich is the subject to the command (ex.: if the command_id is death, the character with id
character_id will die in each client wich are recieved the packet)
command_id: this determines what will happen to the character with character_id, also it determines the command_data field's
size (migth be 0) (ex.: the command death doesnt require any additional info)
command_data: any info needed by the client to complete the command command_id
A good way to determine where a command starts is checking your character_id at the beginning of the packet (since that id is your char's id if you recorded your gameplay). Than just search for other appearances of this id.
Packets sent by the loginserver to the client:
command_id desc command_data
0 greet [(int)magic]
0xfd server list
0xfe login refuse [(int)error_type] some error types: 0x79: wrong id, 0x78: wrong password, 0x6d: service unavaliable
Packets sent by the client to the loginserver:
command_id desc command_data
0x18 unknown none
0xfc server list request [(pstr)client compile date][(pstr)unknown][(pstr)username][(pstr)password]
packets sent by the characterserver to the client:
command_id desc command_data
0 greet [(int)magic]
0x0b [(int)s][(int)magic][(int)magic]
0x11 first packet after login [(int)magic][(int)magic][(int)magic][(int)magic]
0x14 this should only be sent after [(int)s] (sends back the last saved s field)
the client authenticated itself
the client will keep calling this while it runs, and the characterserver should allways repply, else the player gets dc.
0xf2 only sent after authentication [(pstr)serverip]
0xf3 character informations [(int)s][(int)n_chars][character_data][(int)n_chars][additional_data]
nchars=number of characters
character data sent n_chars times, with the data of the nth char.
additional_data sent n_chars times, structure:
[(byte)0][(int)0][(int)0][(int)0]
packets sent by the client to the character server:
0x0b unknown none
0x11 should answer with 0x14 if none
the client isnt authenticated
itself yet, nothing otherwise
0x14 answers with 0x0b without the character list shown, 0x14 after
0xf4 character create [(pstr)username][(pstr)password][(byte)slotid][(pstr)character_name]
slotid: 0=left, 1=middle, 2=rigth
0xf5 character delete [(pstr)username][(pstr)password][(pstr)unknown][(int)character_id]
0xf6 character list [(pstr)unknown_date][(pstr)username][(pstr)password]
0xff05 last packet before worldserver [(pstr)user][(int)unknown][(pstr)character_name]
The characterserver has a pretty nice "dance" here, if you make one step wrong, the client migth freeze.
The authentication is complete when the client send your username and password the first time (the characterserver will repply to this packet with the character list)
The dance is like this:
if Client sends 0x0b, server repplies with 0x11
if the client sends 0x11, the server repplies 0x14 ONLY if the client hasnt autheticated yet
if the client sends 0x14, the server repplies 0x0b if not authenticated, 0x14 if authenticated
if the client sends 0xf6, itll get authenticated, and the server should send 0xf2 (ip), than 0xf6(charlist) rigth after
from hereon the charserver shouldnt do anything, (itll just keep repplying to the clients 0x14's with 0x14's, (else the client will get dc))
after you choosen your character, the client will send a 0xff05, and connect to the worldserver after it recieved the answer from 0xff05
Worldserver:
I begin with some text here.
For the first packet, you recieve a damn long and big and important and whatnot packet.
Its a spawning packet, basically spawns your character into the world. And its contains nearly every damn information to do it.
command_id desc structure
0xf0 spawn, damn lot of variations of this packet
0xf1 desapwn(remove) none
0xf2 mapchange [(int)mapid][(float)x][(float)y][(float)z]
0x98 special motions [(int)motion id] (ex.: 4=sitdown/standup)
0xc1 movetoxyz [(float)x][(float)y][(float)z][(byte)1]
0xc2 movetochar [(int)character_id][(int)0]
0xc7 death [(int)killer_character_id][(int)0x29]
0xc8 teleport [(float)x][(float)y][(float)z][(int)0][(int)0][(int)0][(int)0][(int)1][(int)0][(int)0][(int)-1][(int)4][(int)0][(int)0][(int)0]
0xcb motionok [(float)x][(float)y][(float)z]...etc...
0xcc flying [(float)x][(float)y][(float)z]...etc...
0xe0 attackmotion [(int)motion_id][(int)target_character_id][(int)0][(int)0x10000]
0x13 damage (numbers) [(int)attacker_id][(int)damage][(int)flags]
0x0f effect(like success/failure) [(int)effect id][(float)x=0][(float)y=0][(float)z=0][(int)0] (if x,y,z=0 here, the client will
use the characters x,y,z who got the command)
0x19 skilleffect [(int)skill_id][(int)skill level][(int)target_character_id][(int)0][(int)3]
0xa0 green text [(byte)1][(pstr)text]
0xd0 shout [(int)shouter_character's id (migth not visible in client)][(pstr)shouter_char_name][(pstr)text]
0x01 chat [(pstr)text]