Hobbistic project with a goal to reimplement Terraria Server with C++ and learn more about Sockets, Server Networking and Terraria Network Protocol communication. During development, I use a set of tools and documentation websites to help get up-to-date information about how Terraria Network Protocol (TNP) communicates, what messages structure looks like, what data types it uses.
- Wireshark's network traffic analysis
- Terraria Native Server
- Terraria Decompiled Source Code
- Terrafirma Documentation
- TShock Documentation
- TShock Source Code
🛠️ Under development🛠️
Server handles client's connection, protocol version verification, requesting and receiving password and assigning player slot.
Note
Currently only Linux is supported as it relies on builtin socket library.
- Phase 1 - Client Connection:
- Accept Connection from client (01) and reply with custom error message (02)
- Request client for password (25), receive password (26) and reply with custom error messages depending on password match
- Assign player slot replaying with (03) message
- Phase 2 - Handle Player & World Information:
- Handle player information from client
- Handle world information from client
| ID (int) | ID (byte) | Message Name | Direction |
|---|---|---|---|
| 1 | 0x01 | Connect Request | Client -> Server |
| 2 | 0x02 | Fatal Error / Disconnect | Server -> Client |
| 3 | 0x03 | Connection Approved / Assign Player Slot | Server -> Client |
| 37 | 0x25 | Request Password | Server -> Client |
| 38 | 0x26 | Send Password / Login with Passoword | Client -> Server |
Below are details about packet messages structures sent between Terraria's Server and Client that I currently managed to determine with help of Wireshark and available documentation on the internet. (this section will be updated as project grows)
Every packet sent in either direction uses the same base package structure.
| Offset | Byte Offset | Size (bytes) | Type | Description | Notes |
|---|---|---|---|---|---|
| 0-1 | 1-2 | 2 | Int16/short/short int | Length of whole packet in bytes | This value is always 3 + Payload's Byte Size because it is a SUM of entire message size expressed in "how many bytes length the message is". Base Packet has size of 3 because first 2 bytes is for length and 3rd byte is for type, so 3 bytes length + length of rest of the message which depends on type and content of packet's data. |
| 2 | 3 | 1 | unsigned byte/byte/unsigned char/char | Packet Type / ID | ID of packet type represented as HEX byte value |
| 3+ | 4+ | ? | ? | Packet Data / Payload | Size and Type depends on message type |
Direction: Server ← Client
Type/ID: 0x01
This is the first message sent by the client to the server when it connects. It notifies server of the Terraria Network Protocol version client use.
Structure Details
| Offset | Byte Offset | Size (bytes) | Type | Description | Notes |
|---|---|---|---|---|---|
| 3 | 4 | 1 | unsigned_byte/byte/unsigned_char/char | Text Message Size | |
| 4+ | 5+ | ? | String | Text Message Content | Content of this text message is always the word "Terraria" concatented with the current version of Network Protocol, ex. "Terraria279" - ("Terraria" + Main.curRelease) |
Direction: Server → Client
Type/ID: 0x02
Structure Details
| Offset | Byte Offset | Size (bytes) | Type | Description | Notes |
|---|---|---|---|---|---|
| 3 | 4 | 1 | unsigned_byte/byte/unsigned_char/char | Network Text Mode | This can be one of:LITERAL = 0x00,FORMATTABLE = 0x01,LOCALIZATION_KEY = 0x02,SUBSTITUTION = 0x03 |
| 4 | 5 | 1 | unsigned_byte/byte/unsigned_char/char | Text Message Size | Size of Text Message Content's sent in this packet |
| 5+ | 6+ | 1 | string | Text Message Content | Error Message's Text Content. Can be any message when used with LITERAL Text Mode. Terraria uses LOCALIZATION_KEY for most messages since this support errors display in multiple languages that are accessed by KEYS specified inside json file. |
Direction: Server ↔ Client
Type/ID: 0x25
Important
First packet with player info is sent by client to server when connecting, but later synchronization occurs between all connected players with server in the middle (Player_A → Server → Player_B and vice versa).
Structure Details
| Offset | Byte Offset | Size (bytes) | Type | Description | Notes |
|---|---|---|---|---|---|
| 3 | 4 | 1 | unsigned_byte/byte/unsigned_char/char | Player ID | Unique ID assigned by server to player when approving connection |
| 4 | 5 | 1 | unsigned_byte/byte/unsigned_char/char | Skin Variant | |
| 5 | 6 | 1 | unsigned byte/byte/unsigned char/char | Voice Variant | Added in 1.4.5 |
| 6-9 | 7-10 | 4 | float | Voice Pitch Offset | Added in 1.4.5, Supposed range from 0.00 to 1.00 (not confirmed) |
| 10 | 11 | 1 | unsigned_byte/byte/unsigned_char/char | Hair Type | If >162 then Set To 0 (for 1.4.9.x, on 1.4.5 update there are new hair types added) |
| 11-(SizeOfIt) | 11-(Size of it) | 1-20 | string | Player Name | Minimum 1 character and maximum 20 characters. |
| +1 | +1 | 1 | unsigned_byte/byte/unsigned_char/char | Hair Dye | |
| +1 | +1 | 1 | bool/unsigned_byte/byte/unsigned_char/char | Hide Visuals | |
| +1 | +1 | 1 | bool/unsigned_byte/byte/unsigned_char/char | Hide Visuals 2 | |
| +1 | +1 | 1 | bool/unsigned_byte/byte/unsigned_char/char | Hide Misc | |
| +3 | +3 | 3 | Color (custom type) | Hair Color | |
| +3 | +3 | 3 | Color (custom type) | Skin Color | |
| +3 | +3 | 3 | Color (custom type) | Eye Color | |
| +3 | +3 | 3 | Color (custom type) | Shirt Color | |
| +3 | +3 | 3 | Color (custom type) | Under Shirt Color | |
| +3 | +3 | 3 | Color (custom type) | Pants Color | |
| +3 | +3 | 3 | Color (custom type) | Shoe Color | |
| +1 | +1 | 1 | unsigned_byte/byte/unsigned_char/char | Difficulty Flags | BitFlags: 0 = Softcore, 1 = Mediumcore, 2 = Hardcore, 4 = ExtraAccessory, 8 = Creative |
| +1 | +1 | 1 | unsigned_byte/byte/unsigned_char/char | Torch Flags | BitFlags: 1 = UsingBiomeTorches, 2 = HappyFunTorchTime, 4 = unlockedBiomeTorches |
Note
Player Info packet can have size ranging from 36 up to 55 bytes long depending on the size of Player Name string
Direction: Server → Client
Type/ID: 0x25
Structure Details
This message has no data/payload. Server sends basic package of size
3 byteswith type of0x25to client. When client recieves this type of packet, prompts user for password and when user type it, client send back to server packet #38
Direction: Server ← Client
Type/ID: 0x26
This message is very similar to #1. Client sends to a server packet with
Structure Details
| Offset | Byte Offset | Size (bytes) | Type | Description | Notes |
|---|---|---|---|---|---|
| 3 | 4 | 1 | unsigned byte/byte/unsigned char/char | Text Message Size | |
| 4+ | 5+ | ? | String | Text Message Content | Password send by client |
Color type is just a structure to store 3 bytes of RGB values.
Structure Details
| Size (bytes) | Type | Description | Notes |
|---|---|---|---|
| 1 | unsigned byte/byte/unsigned char/char | RED value | |
| 1 | unsigned byte/byte/unsigned char/char | GREEN value | |
| 1 | unsigned byte/byte/unsigned char/char | BLUE value |
WIP