Network communication in Terraria is done via a series of Messages. It is not a request/response system. The client sends messages when it wants to notify the server or changes (the player moves, for example), and the server sends messages when it wants to notify the client of changes (another player talks, for example).
That said, there are times when certain responses are to be expected. The login process, for example. This is laid out in the last section on this page.
The structure of the general message is defined below.
The types used in messages are little-endian.
Type | Bytes | Notes |
---|---|---|
Byte | 1 | Unsigned 0 .. 255 |
Int16 | 2 | Signed -32,768 .. 32,767 |
Int32 | 4 | Signed -2,147,483,648 .. 2,147,483,647 |
Single | 4 | Single precision float |
Color | 3 | Three unsigned bytes that define R,G,B values |
String | * | ASCII string, length must be derived from message size |
Offset | Type | Description |
---|---|---|
0 | Int32 | Message Length |
1 | Byte | Message Type |
2 | * | Message Payload |
Message Length is the length of Type + Payload in bytes. The smallest message is one without a payload, so Message Length would be 1 in that case.
The Payload is dependent on the Message Type, see below.
What follows is a detailed list of all the available message types. It is also specified if the message is sent by the client or the server or both. The Message IDs are specified in hex, as indicated by the '$'. During the login process, the client is only allowed to send the messages marked with an asterisk. Attempts to send any other message will result in an error, and disconnection.
This is the first message sent by the client to the server when it connects. It also notifies the server of the client version.
Offset | Type | Description |
---|---|---|
0 | String | The word Terraria concatenated with the current version. i.e. "Terraria37" |
The server sends this whenever there is an error. It will drop the connection right after this is sent.
Offset | Type | Description |
---|---|---|
0 | String | The error message. |
The server sends this message when the connection is successful. It also sends the client's assigned player slot. All connected players are assigned a slot, 0-254.
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
This defines a player's appearance and name.
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Hair Style |
2 | Byte | Gender (0=female,1=male) |
3 | Color | Hair Color |
6 | Color | Skin Color |
9 | Color | Eye Color |
12 | Color | Shirt Color |
15 | Color | Undershirt Color |
18 | Color | Pants Color |
21 | Color | Shoe Color |
24 | Byte | Difficulty (0=normal, 1=medium core, 2=hard core) |
25 | String | Player Name |
The client sends this as part of the login process to notify the server of the player's appearance. There is nothing preventing the client from sending this after the login process, however. The server will enforce the player slot, so any attempts to change the appearance of other players will just change your own.
The server will send this to the client to notify the client of other players' appearance. The client should ignore this message if the player slot is its own, since the server is not allowed to change any of this data.
This specifies what item is in a specific inventory slot. Slots 0 to 58 are inventory slots, Slots 59 to 69 are armor/accessory slots. Slots 70 to 72 are dye slots. A stack of 0 means the slot is empty.
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Inventory Slot |
2 | Int16 | Item Stack |
4 | Byte | Item Prefix ID |
5 | Int16 | Item ID |
The client sends this to notify the server of the player's inventory. During the login process, the client sends 59 of these, one for each slot. It also sends this whenever the player modifies their inventory, either by moving something around, or pulling things out of chests, and so on. The server will enforce the player slot, so any attempts to modify the inventory of other players will just modify your own.
The server sends this to notify the client of other players' inventories. The client should ignore this message if the player slot is its own, since the server is not allowed to modify your inventory.
Asks the server for world info. This is done as part of the login process.
None.
This message contains the basic information about the current world.
Offset | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Int32 | Game Time | ||||||||||||||||||
4 | Byte | Day Time (0=No, 1=Yes) | ||||||||||||||||||
5 | Byte | Moon Phase | ||||||||||||||||||
6 | Byte | Blood Moon (0=No, 1=Yes) | ||||||||||||||||||
7 | Byte | Eclipse (0=No, 1=Yes) | ||||||||||||||||||
8 | Int32 | Map Width in Tiles | ||||||||||||||||||
12 | Int32 | Map Height in Tiles | ||||||||||||||||||
16 | Int32 | Spawn Tile X | ||||||||||||||||||
20 | Int32 | Spawn Tile Y | ||||||||||||||||||
24 | Int32 | Ground Level Y | ||||||||||||||||||
28 | Int32 | Rock Layer Y | ||||||||||||||||||
32 | Int32 | World ID | ||||||||||||||||||
36 | Byte | Moon Type | ||||||||||||||||||
37 | Int32[3] | Tree X | ||||||||||||||||||
43 | Byte[4] | Tree Style | ||||||||||||||||||
47 | Int32[3] | Cave Back X | ||||||||||||||||||
59 | Byte[4] | Cave Back Style | ||||||||||||||||||
63 | Byte[8] | Background Styles | ||||||||||||||||||
71 | Byte | Ice Back Style | ||||||||||||||||||
72 | Byte | Jungle Back Style | ||||||||||||||||||
73 | Byte | Hell Back Style | ||||||||||||||||||
74 | Single | Wind Speed | ||||||||||||||||||
78 | Byte | Number of Clouds | ||||||||||||||||||
79 | Byte | Flags:
| ||||||||||||||||||
80 | Byte | Flags:
| ||||||||||||||||||
81 | Single | Max Rain | ||||||||||||||||||
85 | String | World Name |
The client sends this message to the server to request initial tile data. The client specifies the player's spawn X,Y. This may or may not be the same as the server spawn. The server sends a lot of messages in response to this. See the Login process below for more detail.
Offset | Type | Description |
---|---|---|
0 | Int32 | Spawn X |
4 | Int32 | Spawn Y |
The server uses this message to show status text to the client. This text is shown in the upper right corner of the screen. Number of messages is the number of messages the client should show the status text for. If the client receives this message multiple times, the client should queue them up.
Offset | Type | Description |
---|---|---|
0 | Int32 | Number of messages. |
4 | String | Status text |
This contains a small row of tile data, starting at Tile X, Tile Y, and running for Width tiles.
Offset | Type | Description |
---|---|---|
0 | Int16 | Width |
2 | Int32 | Tile X |
6 | Int32 | Tile Y |
10 | * | Tile data |
The tile data is represented like so:
Byte | Flags:
| ||||||||||||||||||
Byte | Flags:
| ||||||||||||||||||
If Has Color:
| |||||||||||||||||||
If Has Wall Color:
| |||||||||||||||||||
If Active:
| |||||||||||||||||||
If Tile has Wall:
| |||||||||||||||||||
If Tile has Liquid:
| |||||||||||||||||||
Int16 | RLE Amount |
The client should recalculate any random U/Vs for this area. This includes the walls.
Offset | Type | Description |
---|---|---|
0 | Int32 | Start X |
4 | Int32 | Start Y |
8 | Int32 | End X |
12 | Int32 | End Y |
Sets player's spawn and respawn them.
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int32 | Spawn X |
5 | Int32 | Spawn Y |
The client sends this at the end of the login process to spawn the player. The server enforces the player slot so attempts to spawn another player will instead respawn the client's player.
The server sends this whenever another player spawns.
Set's the player's current position and velocity, along with their current control state.
Offset | Type | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Byte | Player Slot | ||||||||||||||||
1 | Byte | Control Flags:
| ||||||||||||||||
2 | Byte | Selected Item Slot | ||||||||||||||||
3 | Single | Player Position X | ||||||||||||||||
7 | Single | Player Position Y | ||||||||||||||||
11 | Single | Player Velocity X | ||||||||||||||||
15 | Single | Player Velocity Y | ||||||||||||||||
16 | Byte | Flags:
|
The client sends this when the player presses a control. The server enforces the player slot so attempts to manipulate other players will just manipulate your own.
The server sends this to notify the client of other players' movements. The client should ignore this message if the player slot is the client's, since the server is not allowed to modify any of this information.
Used to disable or enable players.
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Active (0=false, 1=true) |
Unused message.
Used to set the player's health stats
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int16 | Current Health Amount |
3 | Int16 | Maximum Health Amount |
The client sends this as part of the login process. The server enforces the player slot, so attempts to modify another person's health will only modify your own.
The server sends this to notify the client of other player's health. The client should ignore this message if the player slot is the client's, since the server is not allowed to modify the player's health this way.
Used to modify the world one tile at a time.
Offset | Type | Description | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Byte | Modify Mode:
| ||||||||||||||||||||||||||||||||
1 | Int32 | Tile X | ||||||||||||||||||||||||||||||||
5 | Int32 | Tile Y | ||||||||||||||||||||||||||||||||
9 | Byte | Tile/Wall ID | ||||||||||||||||||||||||||||||||
10 | Byte | Tile Variant |
Sent by the client when the player modifies a tile.
Sent by the server when someone else modifies a tile.
Sets the current game time.
Offset | Type | Description |
---|---|---|
0 | Byte | Day/Night (0=Night,1=Day) |
1 | Int32 | Time |
5 | Int16 | Sun Mod Y |
7 | Int16 | Moon Mod Y |
Open or Close a door
Offset | Type | Description |
---|---|---|
0 | Byte | 0 = Open, 1 = Close |
1 | Int32 | Tile X |
5 | Int32 | Tile Y |
9 | Byte | Facing Direction (0 = left, 1 = right) |
Sent when the player opens or closes a door.
Sent when someone else opens or closes a door.
Updates a Length x Length block of tiles.
Offset | Type | Description |
---|---|---|
0 | Int16 | Length |
2 | Int32 | Tile X |
6 | Int32 | Tile Y |
10 | * | Tile Data |
Tile Data is stored exactly the same as it is stored in Message $0A, except the RLE is not present. There are Length x Length tiles represented
I don't know why the client is allowed to send this. Especially since it doesn't go through anti-spam filters.
Sent when the server needs to update a chunk of blocks, like with falling sand. The client should update the U/V of the received tiles.
An item is modified in the world.
Offset | Type | Description |
---|---|---|
0 | Int16 | Item Slot |
2 | Single | Position X |
6 | Single | Position Y |
10 | Single | Velocity X |
14 | Single | Velocity Y |
18 | Int16 | Stack Amount |
20 | Byte | Prefix ID |
21 | Byte | Own Ignore |
22 | Int16 | Item ID |
If Item ID is 0, this item slot is considered inactive.
Sent when a the player modifies an item in the world. If the item is to be created, Item Slot should be 200.
Sent when an item in the world is modified. If the player created the item, the server won't tell the player about the item for a set amount of time, to prevent the player from accidentally picking it back up.
Sets the owner of an item on the ground.
Offset | Type | Description |
---|---|---|
0 | Int16 | Item Slot |
2 | Byte | Owner Player Slot |
The client does this to disown an item. Setting the owner to 255. You can only do this for items you own. The server will force the new owner to be no one.
The server sends this to notify the client of the owner of an item.
Sets info about an NPC. This could be either a friendly NPC or a Mob.
Offset | Type | Description | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Int16 | NPC Slot | ||||||||||||||||
2 | Single | Position X | ||||||||||||||||
6 | Single | Position Y | ||||||||||||||||
10 | Single | Velocity X | ||||||||||||||||
14 | Single | Velocity Y | ||||||||||||||||
18 | Byte | Target | ||||||||||||||||
19 | Byte | Flags:
| ||||||||||||||||
20 | Int32 | Life | ||||||||||||||||
24 | Single[4] | AI (depends on flags) | ||||||||||||||||
* | Int16 | NPC ID |
An NPC with Life of 0 means the NPC is not active.
AI is a series of floats that somehow determine how the NPC moves
Hit an NPC with your currently equiped item
Offset | Type | Description |
---|---|---|
0 | Int16 | NPC Slot |
2 | Byte | Player Slot |
The client does this when the player hits an NPC. The server will enforce the Player slot, so you cannot force another player to hit something.
The server sends this when another player hits an NPC. This may even be your own player, the server is able to force that.
Text chat
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Color | Text Color |
4 | String | Chat Text |
The client sends this when the player says something. The client doesn't parse any special commands.
The server sends this when another player (or the server) says something. The server will not prefix the player's name in the text, it's up to the client to do that. A player slot of 255 means the client should not prefix the player's name since it is either a server message, or a player action.
Player takes damage, or attacks another player
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Hit Direction |
2 | Int16 | Damage |
4 | Byte | PvP (0=self damage, 1=PvP) |
5 | Byte | Critical Hit (0=No, 1=Yes) |
6 | String | Death Text |
Client sends this to attack another player. The server will ignore this message unless both players have PvP enabled.
The server will send this if you or another player takes damage for any reason.
Create or modify a projectile
Offset | Type | Description |
---|---|---|
0 | Int16 | Projectile Identity |
2 | Single | Position X |
6 | Single | Position Y |
10 | Single | Velocity X |
14 | Single | Velocity Y |
18 | Single | Knock Back |
22 | Int16 | Damage |
24 | Byte | Owner Player Slot |
25 | Int16 | Projectile Type |
27 | Single[4] | AI |
Projectiles have Identities rather than slots because they are so numerous. Projectiles instead are identified by their identity (random id), and owner slot
Client sends this when a player creates or somehow modifies a projectile.
The server sends this whenever another player creates or modifies a projectile.
NPC is damaged, by projectile or other means. Passing a negative damage value will insta-kill the NPC.
Offset | Type | Description |
---|---|---|
0 | Int16 | NPC Slot |
2 | Int16 | Damage |
4 | Single | Knockback |
8 | Byte | Direction 0= |
9 | Byte | Critical Hit (0 = no, 1 = yes) |
The client sends this when an NPC is hit by a projectile or harmed by other means
The server sends this when it determines the NPC is harmed
Remove projectile
Offset | Type | Description |
---|---|---|
0 | Int16 | Projectile Identity |
1 | Byte | Owner Player Slot |
The client sends this when a projectile is destroyed. The server enforces the player slot, so you may not delete other players' projectiles
The server sends this when a projectile is destroyed by another player.
Turns PvP on or off
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | PvP (0 = off, 1 = on) |
The client sends this when the player toggles PvP. The server enforces the player slot, so attempts to toggle someone elses' PvP will simply toggle your own.
This is sent by the server, along with a chat message, whenever someone else toggles PvP.
Requests the contents of a chest.
Offset | Type | Description |
---|---|---|
0 | Int32 | Tile X |
4 | Int32 | Tile Y |
Identifies an item in a chest
Offset | Type | Description |
---|---|---|
0 | Int16 | Chest Slot |
2 | Byte | Item Slot |
3 | Int16 | Stack |
5 | Byte | Prefix ID |
6 | Int16 | Item ID |
The client sends this whenever the player modifies the contents of a chest. Either by adding or removing something, or just moving items around.
The server sends this when you request the contents of the chest. It does not broadcast other players' modifications of chests.
Flags a chest as open or closed.
Offset | Type | Description |
---|---|---|
0 | Int16 | Chest Slot |
2 | Int32 | Tile X |
6 | Int32 | Tile Y |
The client calls this with chest slot -1 to signify that they've closed the chest.
The server sends this when it's finished sending the contents of a chest, to indicate that the chest is now opened by you. It may also send -1 if the chest is forced closed for any reason.
Breaks a chest, or does nothing if the chest is full
Offset | Type | Description |
---|---|---|
0 | Int32 | Tile X |
4 | Int32 | Tile Y |
Heals a player
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int16 | Heal amount |
Sent when the player uses a potion or heals himself somehow. The server enforces the player slot, so you cannot heal someone else.
Sent by the server when another player heals himself, or if something out of the player's control heals the player.
Sets the player's zones
Offset | Type | Description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Byte | Player Slot | ||||||||||||||||||
1 | Byte | Flags:
|
Sent by the client to let the server know what zones are currently active based on the types of tiles in the area.
Sent by the server to notify the client about the zones of other players.
Server requires a password to join. After the server sends this, it will accept no other packets except for $26.
None
Sends the server password.
Offset | Type | Description |
---|---|---|
0 | String | Password |
Unassigns an item on the ground. This works just like $16, except the new owner is always nobody (255).
Offset | Type | Description |
---|---|---|
0 | Int16 | Item Slot |
Talks to an NPC
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int16 | NPC Slot |
The client sends this when the player talks to a friendly NPC. The server enforces the player slot, so you cannot force other players to talk to NPCs.
The server sends this to notify you that other players (or yourself) are talking to an NPC.
Animates an item carried by a player
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Single | Item Rotation |
5 | Int16 | Item Animation |
The client sends this to animate flails. The server enforces the player slot, so you may not animate other players' flails.
The server sends this to notify the client of other player's animations.
Sets player's mana and max mana
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int16 | Mana level |
3 | Int16 | Max Mana |
Client sends this as part of the login to specify the mana levels. The server enforces the player slot, so you may not set mana for another player.
The server sends this to notify you of other player's mana levels, or to adjust your own.
Rejuvenates player mana
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int16 | Regeneration amount |
Client sends this when the player takes a mana potion or some other mana regeneration. The server enforces the player slot so you can't rejuvenate another player's mana.
Server sends this to notify you of other player's mana regeneration, or to affect your own.
Kills a player
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Hit Direction |
2 | Int16 | Damage |
4 | Byte | PvP (1 = Result of PvP) |
5 | String | Death Message |
Client sends this if the player dies. The server enforces the player slot so you cannot kill another player.
The server sends this to notify the client of another players' death. The client should ignore this message if the player slot is the clients.
Changes the player's party
Offset | Type | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Byte | Player Slot | ||||||||||||
1 | Byte | Team:
|
Client sends this when the player changes parties. The server enforces the player slot so you cannot affect the parties of other players.
Server sends this when another player changes parties, or if your party is changed somehow.
Requests to read a sign
Offset | Type | Description |
---|---|---|
0 | Int32 | Tile X |
4 | Int32 | Tile Y |
Changes a sign's text.
Offset | Type | Description |
---|---|---|
0 | Int16 | Sign Slot |
2 | Int32 | Sign X |
6 | Int32 | Sign Y |
10 | String | Sign Text |
The client sends this when the player changes the text on a sign.
The server sends this when the player requests to read a sign.
Adjust the liquid at a tile
Offset | Type | Description |
---|---|---|
0 | Int32 | Tile X |
4 | Int32 | Tile Y |
8 | Byte | Liquid Amount |
9 | Byte | Liquid Type (0 = water, 1 = lava) |
Client sends this when a player dumps liquid on the ground.
Server sends this to notify the client of flowing liquid.
Initialization complete, request to spawn.
None.
Set's the player's active buffs
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte[10] | Buff types |
Client sends this during initialization, or when the player activates multiple buffs. The server enforces the player slot, so you cannot change the buffs of another player.
Server sends this to notify you of other players' buffs. You should ignore this if the player slot is the clients', since the server is not allowed to modify your buffs.
Answer's the old man's question to free him of the curse
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | 1 = Spawn Skeletron, 2 = Don't. |
Client sends this as a response to the old man's question, either to take on skeletron, or not.
The server sends this if another player declined to break the curse.
Unlocks a chest or door
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Unlock (0 = no, 1 = yes) |
2 | Int32 | Tile X |
6 | Int32 | Tile Y |
The client sends this to unlock a locked chest or door.
The server sends this to notify the client that someone else unlocked a chest or door.
Adds a buff to an NPC
Offset | Type | Description |
---|---|---|
0 | Int16 | NPC Slot |
2 | Byte | Buff Type |
3 | Int16 | Buff Time |
Client sends this to notify the server that an NPC was buffed.
Server sends this whenever an NPC was buffed.
Sets all of an NPC's buffs
Offset | Type | Description |
---|---|---|
0 | Int16 | NPC Slot |
2 | Buff[5] | NPC Buff |
The structure of each Buff is:
Offset | Type | Description |
---|---|---|
0 | Byte | Buff Type |
1 | Int16 | Buff Time |
Adds a buff to a player
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Byte | Buff Type |
2 | Int16 | Buff Time |
The client sends this when the player adds a single buff.
The server sends this when your player was buffed. The client should ignore this if the player slot isn't the client's.
Sets the name of an NPC
Offset | Type | Description |
---|---|---|
0 | Int16 | NPC Slot |
2 | String | NPC Name |
Sets the amount of hallowed vs corruption
Offset | Type | Description |
---|---|---|
0 | Byte | Amount of Hallowed |
1 | Byte | Amount of Corruption |
Plays a harp
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Single | Note |
Sent when the player plays a harp. The server enforces the player slot, so you cannot force another player to play a harp.
Sent when another player plays a harp.
Flips a switch
Offset | Type | Description |
---|---|---|
0 | Int32 | Tile X |
4 | Int32 | Tile Y |
Sent when the player flips a switch.
Sent when another player flips a switch.
Moves an NPC home
Offset | Type | Description |
---|---|---|
0 | Int16 | NPC Slot |
2 | Int16 | Home X |
4 | Int16 | Home Y |
6 | Byte | Homeless (0 = no, 1 = yes) |
Sent when the player moves an NPC's home, or makes an NPC homeless using the housing menu.
Sent when another player moves an NPC's home, or an NPC moves in on its own.
Summons a boss or invasion at player position
Offset | Type | Description |
---|---|---|
0 | Int32 | Player ID |
4 | Int32 | Boss/Invasion Type |
Perform a Ninja or Shadow Dodge
Offset | Type | Description |
---|---|---|
0 | Int32 | Player ID |
4 | Int32 | Dodge Type |
Sent when client performs the dodge
Sent to announce to other players that the player dodged
Paints a tile
Offset | Type | Description |
---|---|---|
0 | Int32 | Tile X |
4 | Int32 | Tile Y |
8 | Byte | Color |
Sent when client paints a tile
Sent to announce to other players of a paint change
Paints a wall
Offset | Type | Description |
---|---|---|
0 | Int32 | Wall X |
4 | Int32 | Wall Y |
8 | Byte | Color |
Sent when client paints a wall
Sent to announce to other players of a paint change
Teleports a player or NPC with an animation
Offset | Type | Description | ||||||
---|---|---|---|---|---|---|---|---|
0 | byte | Flags:
| ||||||
1 | Int16 | Player Slot | ||||||
3 | Single | Destination X | ||||||
7 | Single | Destination Y |
Sent when player teleports
Sent when NPC or other player teleports
Quick heal player
Offset | Type | Description |
---|---|---|
0 | Byte | Player Slot |
1 | Int16 | Heal Amount |
Sent when client heals himself
Sent when other player heals
Unknown
Offset | Type | Description |
---|---|---|
0 | String | Unknown |
Certain messages expect certain responses, some messages take on different meanings when coming from the server or the client. I figured I'd cover the basics here.
The client is only allowed to send messages marked with an asterisk until it goes through the login process and the server bumps your state up to Playing (10).
When the client does something like notify the server of the player appearance (by sending $04), the server will take note of that information, and then echo that same information back to all connected clients... including the person who sent the information in the first place. This means for many messages, you might get an echo back.
When a client connects to a server, it sends $01 as the first message. The server will then respond with either $03 if your connection was approved or $25 if the server requires a password. The server may also respond with $02 if your IP was banned.
If a password is required, the client should then send the password with $26. The server will then respond as before; $03 if approved, $02 if there was a problem. Once you're approved, the server classifies your connection as Initializing (1).
Once the client receives $03, it should send $04 to notify the server of the player's appearance. Then, without waiting for a response, it should send $10 to set the player life, $2a to set the player's mana, and $32 to set the player's buffs. Next, the client should loop through the player's inventory slots (0 to 72) and send $05 for each one. Finally the client should send $06 to request world information.
If the server has a problem with your name set in $04, it will kick you with an error ($02).. otherwise the server will be echoing out your information to all other clients. Finally, the server will respond to your request for world information with $07. It will then bump your state up to Initialized (2).
Once the client receives $07, it should send request the initial tile data for the spawn with $08, giving it the spawn X and spawn Y it received with the world information.
The server will respond to $08 by sending a status update $09, followed by several $0A around the spawn. It will send $0B telling you to recalculate the areas that need recalculating. Then it will send $15 and $16 for items on the ground. It will also send $17 for all NPCs in the world. Then it will send $31 telling the client to spawn, $39 giving the balance stats for the world, and finally $38 for all Named NPCs.
When the client receives $31, it should then send $0C to spawn the character in the world. At this point the server kicks your state up to Playing (10). After this, any messages can be sent between the client and server.