Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This page describes TERA's network protocol, which is built on top of TCP. It is a structured protocol that can be serialized and deserialized automatically based on uniform packet definitions; no special serialization logic is required for any fields.
C/C++-like primitive types and struct
s will be used.
bool
is equivalent to uint8_t
but only allows the values true
(1
) and false
(0
).
Integers (uint8_t
, int8_t
, uint16_t
, int16_t
, etc) are little endian.
offset_t
values are uint16_t
indexes into a packet, including the header.
float
and double
are IEEE 754 binary32
and binary64
, respectively.
Characters (i.e. char16_t
) are UTF-16 and little endian.
Strings (i.e. u16string
) are a series of valid char16_t
characters followed by a NUL character.
Fields are laid out in the declared order with no implied padding anywhere.
TODO: Describe the (insecure) key exchange and the PIKE algorithm.
A packet starts with a simple header:
length
specifies the full length of the packet, including the header. Thus, the maximum length of a packet is 65535
bytes (or 65531
bytes for the payload). For certain large packets (e.g. achievements and inventory), the game works around this by sending 'continuation' packets after the first packet.
code
is the operation code. This tells the client or server what the structure of the payload is.
The packet body consists of a series of fields. Some examples:
Fields are written in the order that they are declared. However, complex fields (strings, object arrays, and byte arrays) are written as offset_t
values that point to the actual data elsewhere in the payload. Primitive types such as integers, floating point numbers, and Boolean values are written in the obvious way as they appear.
Complex types are written after all primitive types in the current 'object' (be that the root packet body, or an object nested arbitrarily within arrays). At the place where the complex field appears, an offset_t
value is written pointing to where the actual data for the field is written in the payload. For object arrays and byte arrays, this value is accompanied by a uint16_t
value representing the number of elements in the array.
When there are multiple complex fields in an object, they are written at the end of the object in the order that they appear in the structure. For example, in CEditPrivateChannelPacket
, the contents of the members
array are written after password
, and the channel_name
string contents after that.
String pointers are represented as follows:
When writing the string contents, the characters are written contiguously, followed by a NUL character.
Object array pointers are represented as follows:
Each element within the array has an object pointer that links to the next element:
start
points to a PacketObjectPointer
, which is immediately followed by the contents of the first element. The next
pointer points to another PacketObjectPointer
, which is immediately followed by the contents of the second element, and so on. This continues count
times. The next
value for the last element is 0
. In each element, here
is just a pointer to itself; it is not clear what purpose it serves.
Due to the way that arrays are serialized, in theory, it would be possible to spread the elements all over the place in a payload, in whatever way would make the most sense for compactness and locality. In practice, the client and official servers almost always do the straightforward thing, with only a few curious (and seemingly nonsensical) exceptions. Regardless, neither party actually cares how arrays are laid out for the purposes of serialization.
Byte array pointers are represented as follows:
Note that count
comes after start
, unlike object arrays.
Byte arrays are serialized in a more compact fashion than object arrays: start
points to an area in the payload containing count
bytes, making up the contents of the byte array. There are no pointer values to follow for each individual element.
Novadrop provides a collection of libraries, tools, and documentation for modifying the TERA game client.
Development of TERA stopped on April 20, 2022. Official game servers shut down on June 30 in the same year. Some of the knowledge and functionality provided by Novadrop was previously held in relative secrecy by a small portion of the game's third-party modding community for the sake of preserving game integrity. With the game effectively defunct, Novadrop now enables the game's community to freely analyze and modify the client, e.g. for the purposes of creating unofficial server emulators.
TODO: Describe the package file format (GPK).
This page describes the encrypted resource container format used by TERA.
C/C++-like primitive types and struct
s will be used.
Integers (uint8_t
, int8_t
, uint16_t
, int16_t
, etc) are little endian.
Characters (i.e. char16_t
) are UTF-16 and little endian.
Strings (i.e. u16string
) are a series of valid char16_t
characters followed by a NUL character.
Fields are laid out in the declared order with no implied padding anywhere.
Portions of resource container files are encrypted with a 256-bit XOR cipher.
The encryption key can be extracted from a TERA client. This can be done with a running TERA process or an unpacked executable. The key appears to be static; it does not change with each client build.
The overall structure can be described like this:
Reading a resource container file requires knowing the full size of the file in advance. A reader must first seek to the footer, read it, then seek to the directory, read and decrypt it, and finally seek to the data where each file entry can be read and decrypted according to the offsets in the directory.
A resource container file ends with this footer:
directory_size
is the size of the directory. This enables a reader to know how far back it must seek in order to read the directory correctly.
magic
must be 0x01001fff
.
Before the footer, there is a directory listing all contained files:
There is no way to know the number of entries in advance; a reader must keep reading entries until it has read the amount of bytes indicated in the footer's directory_size
field.
Note that the entire directory is encrypted with the XOR cipher.
Each entry in the directory is of the form:
size
is the size of the contained file.
offset
indicates where in the data
section the file's contents are located. size
bytes must be readable at this location. Note that the contents are encrypted with the XOR cipher.
name
is the name of the file on disk.
This page describes the encrypted and compressed data center format used by TERA.
C/C++-like primitive types, enum
s, struct
s, and union
s will be used.
bool
is equivalent to uint8_t
but only allows the values true
(1
) and false
(0
).
Integers (uint8_t
, int8_t
, uint16_t
, int16_t
, etc) are little endian.
float
and double
are IEEE 754 binary32
and binary64
, respectively.
Characters (i.e. char16_t
) are UTF-16 and little endian.
Fields are laid out in the declared order with no implied padding anywhere.
Note that the format uses both zero-based and one-based array indexes in various, seemingly random places.
Data center files are encrypted with the AES algorithm in CFB mode and with block, key, and feedback sizes all set to 128 bits. No padding is done for the final block.
The encryption key and initialization vector can both be extracted from a TERA client. This can be done with a running TERA process or an unpacked executable. These values are usually freshly generated for each client build.
The overall structure can be described like this:
After decryption, there is a small header of the form:
All data immediately following this header is compressed with the Deflate algorithm.
uncompressed_size
is the size of the data center file once inflated.
zlib_header
is a zlib (§2.2) header. In official data center files, it is usually of the form 0x9c78
, but it can be any valid zlib header.
After decompression, a data center file starts with this header:
version
is currently 6
. A past version 3
also existed. Note that this field has no distinguishing value for the 32-bit and 64-bit formats, but version 3
was only 32-bit.
timestamp
is a Unix timestamp indicating when the file was produced.
unknown_1
, unknown_2
, unknown_3
, unknown_4
, and unknown5
are all always 0
. They are actually part of a tree structure describing the XSD schema of the data graph, but official data centers never include this information.
revision
indicates the version of the data graph contained within the file. It is sometimes (but not always) equal to the value sent by the client in the C_CHECK_VERSION
packet. This field is not present if version
is 3
.
A data center file ends with this footer:
marker
is always 0
and has no known purpose in the client.
Most of the content in data center files is arranged into regions, which may be segmented. The region structures used throughout the format are described here:
In a DataCenterRegion
, the used_count
can be less than the full_count
. full_count
is usually 65535
, even when used_count
is much smaller. All data in the region that goes beyond used_count
can be arbitrary and should be considered undefined.
A DataCenterSegmentedSimpleRegion
is mostly the same as a DataCenterSegmentedRegion
, with the main difference being that it has a static amount of segments.
Addresses are frequently used to refer to elements within both types of segmented regions:
Here, segment_index
is a zero-based index into the segments
array of the segmented region, while element_index
is a zero-based index into the elements
array of the segment.
All strings, whether they are names or values, are arranged into string tables, which are effectively used as hash tables by the client. A string table has the form:
A string entry in the table
region looks like this:
hash
is a hash code for the string, given by the expression data_center_string_hash(value)
where value
is the string value. In a typical data center file, there is only a very tiny amount of hash collisions.
length
is the length of the string in terms of characters, including the NUL character.
index
is a one-based index into the string table's addresses
region. The address at this index must match the address
field exactly.
address
is an address into the string table's data
region. This address points to the actual string data. The string read from this address must have the same length as the length
field. Notably, if the string data straddles the end of its segment, the NUL character may be omitted. Readers should therefore not rely exclusively on the presence of a NUL character, but also check the segment bounds.
A string entry must be placed in the correct table
segment based on its hash
field. The segment index is given by the expression (hash ^ hash >> 16) % count
where count
is the static size of the table
region. Further, entries in a segment must be sorted by their hash code in ascending order.
For the names
table, the special names __root__
and __value__
must be added to the table last, so that their index values are greater than all other entries. Also, they must be present even if they are not used.
Finally, it is worth noting that the names
table is always referred to by index, whereas the values
table is always referred to by address. The reason for this is that the names
table is small enough that all entries can be accessed by a uint16_t
index value into its addresses
region, whereas that is not the case for the values
table. In spite of this difference, names
and values
must both have valid addresses
regions.
The data_center_string_hash
function is a bizarre variant of CRC32. It is defined as follows:
(Note that string_hash_table
is the same as value_hash_table
.)
The actual content in a data center file is stored as a directed acyclic graph, which is essentially XML serialized to a binary format.
Each node is of the form:
name_index
is a one-based index into the addresses
region of the names
table. If this value is 0
, it indicates that this node has no name or associated data of any kind, and should be disregarded; in this case, all other fields of the node should be considered undefined. Such nodes are usually incidental leftovers in official data center files and need not be present.
key_flags
is 0
in official data center files. It may have a combination of the following values:
If DATA_CENTER_KEY_FLAGS_UNCACHED
is set, the results of a query against this node will not be cached by the client.
key_index
is a zero-based index into the keys
region.
attribute_count
and child_count
indicate how many attributes and child nodes should be read for this node, respectively. If a count field is 0
, then the corresponding address field should be considered undefined, though it will usually be 65535:65535
in official data center files.
attribute_address
is an address into the attributes
region. attribute_count
attributes should be read at this address. These attributes must be sorted by their name index in ascending order.
child_address
is an address into the node
region. child_count
nodes should be read at this address. These children must be sorted first by their name index, then by the values of key attributes (if any), in ascending order. Note that the sort must be stable since the order of multiple sibling nodes with the same name can be significant for the interpretation of the data.
padding_1
and padding_2
should be considered undefined. They were added in the 64-bit data center format, and are not present in the 32-bit format.
The root node of the data graph must be located at the address 0:0
. It must have the name __root__
and have zero attributes.
Keys are used to signal to a data center reading layer (e.g. in the client) that certain attributes of a node will be used frequently for lookups. The reading layer can then decide to construct an optimized lookup table for those specific paths in the graph, transparently making those lookups faster. It is effectively a trade-off between speed and memory usage.
name_index_1
and friends are one-based indexes into the addresses
region of the names
table. A value of 0
indicates that the field does not define a key. A key definition can specify between zero and four keys. These fields may not refer to the special __value__
attribute.
There need not be any keys defined in a data center file at all, but the client will be very slow without certain key definitions. At minimum, a data center file must contain a key definition at index 0
with all fields 0
(i.e. with no keys) which all nodes can point to by default.
Each node in the data graph has zero or more attributes, which are name/value pairs. They are of the form:
name_index
is a one-based index into the addresses
region of the names
table.
type_code
specifies the kind of value the attribute holds. Valid values are as follows:
extended_code
specifies extra information based on the value of type_code
:
If type_code
is DATA_CENTER_TYPE_CODE_INT
, then the lowest bit of extended_code
is set if the attribute's value should be considered a Boolean, meaning that value
can only be 1
(true
) or 0
(false
). Either way, the higher bits are 0
.
If type_code
is DATA_CENTER_TYPE_CODE_FLOAT
, then extended_code
is 0
.
If type_code
is DATA_CENTER_TYPE_CODE_STRING
, then extended_code
is given by the expression data_center_value_hash(value)
where value
is the string value.
value
holds the attribute value and is interpreted according to type_code
and extended_code
. In the case of DATA_CENTER_TYPE_CODE_STRING
, the a
field holds an address into the data
region of the values
table. For other type codes, the value is written directly and is accessed through the i
, b
, or f
fields.
padding_1
should be considered undefined. It was added in the 64-bit data center format, and is not present in the 32-bit format.
Some nodes will have a special attribute named __value__
. In XML terms, this represents the text of a node. For example, <Foo>bar</Foo>
would be serialized to a node called Foo
containing an attribute named __value__
with the string value bar
. It is worth noting that a node can have both text and child nodes, such as Foo
in this example:
Note that the __value__
attribute, if present, may only be a string.
The data_center_value_hash
function uses a bizarre variant of CRC32 combined with a minimal effort to ignore the casing of characters. It is defined as follows:
(Note that value_hash_table
is the same as string_hash_table
.)
The novadrop-dc tool allows manipulation of TERA's data center files. It supports the following tasks:
Reasonably accurate inference of XSD schemas from a packed data center file.
Validation of data sheets against schemas, preventing many mistakes when authoring data sheets.
Packing of data sheets in accordance with type and key information in schemas to a fresh data center file usable by the client.
Format integrity verification of data center files, optionally with strict compliance checks.
Support for various iterations of the data center format throughout the game's history.
In general, novadrop-dc is quite fast: It exploits as many cores as are available for parallel extraction, validation, and packing. On a modern system, unpacking an official data center file takes around 15 seconds, while packing the resulting data sheets takes around 25 seconds.
Packs the data sheets in a directory to a data center file. If validation of the data sheets fails during packing, a list of problems will be printed and the exit code will be non-zero.
The input
argument specifies a directory containing data sheets and schemas. The output
argument specifies the path of the resulting data center file.
--format <format>
Specifies the data center format variant (defaults to V6X64
).
--revision <value>
Specifies the data tree revision number (defaults to latest known revision).
--compression <level>
Specifies a compression level (defaults to Optimal
).
--encryption-key <key>
Specifies an encryption key (defaults to the latest known key).
--encryption-iv <iv>
Specifies an encryption IV (defaults to the latest known IV).
Repacks a data center file without unpacking to disk. This command is primarily useful for development of novadrop-dc.
The input
argument specifies the input data center file. The output
argument specifies the path of the resulting data center file.
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--decryption-iv <iv>
Specifies a decryption IV (defaults to the latest known IV).
--architecture <architecture>
Specifies the data center format architecture (defaults to X64
).
--strict
Enables strict format compliance checks while reading the input file.
--format <format>
Specifies the data center format variant (defaults to V6X64
).
--revision <value>
Specifies the data tree revision number (defaults to latest known revision).
--compression <level>
Specifies a compression level (defaults to Optimal
).
--encryption-key <key>
Specifies an encryption key (defaults to the latest known key).
--encryption-iv <iv>
Specifies an encryption IV (defaults to the latest known IV).
Performs best-effort inference of the schemas for the data tree in a data center file. This may be useful when working with older data centers for which Novadrop's included schemas are not correct.
Please note that, regardless of whether the Conservative
or Aggressive
inference strategy is used, the generated schemas will require a human touch after they have been generated. Among other things, this command cannot tell whether a given path in the tree with repeated node names represents a truly recursive structure.
The input
argument specifies the input data center file. The output
argument specifies the path of the directory to write inferred schemas to.
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--decryption-iv <iv>
Specifies a decryption IV (defaults to the latest known IV).
--architecture <architecture>
Specifies the data center format architecture (defaults to X64
).
--strict
Enables strict format compliance checks while reading the input file.
--strategy <level>
Specifies a schema inference strategy (defaults to Conservative
).
--subdirectories
Enables using output subdirectories based on data sheet names.
Unpacks the data tree in a data center file to a series of data sheets and schemas in a directory. This command is primarily intended for unpacking official data center files into a form that is easily maintainable by humans.
The input
argument specifies the input data center file. The output
argument specifies the path of the directory to extract data sheets and schemas to.
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--decryption-iv <iv>
Specifies a decryption IV (defaults to the latest known IV).
--architecture <architecture>
Specifies the data center format architecture (defaults to X64
).
--strict
Enables strict format compliance checks while reading the input file.
Validates the data sheets in a directory against their schemas. If validation of the data sheets fails, a list of problems will be printed and the exit code will be non-zero.
The input
argument specifies a directory containing data sheets and schemas.
Verifies the format integrity of a data center file. This means traversing the entire data tree, reading all nodes and attributes, and ensuring that no errors occur.
The input
argument specifies the input data center file.
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--decryption-iv <iv>
Specifies a decryption IV (defaults to the latest known IV).
--architecture <architecture>
Specifies the data center format architecture (defaults to X64
).
--strict
Enables strict format compliance checks while reading the input file.
The novadrop-rc tool allows manipulation of TERA's resource container files. It supports the following tasks:
Extraction of files contained within resource container files.
Packing of files to a fresh resource container file usable by the client.
Format integrity verification of resource container files, optionally with strict compliance checks.
Packs the files in a directory to a resource container file.
The input
argument specifies a directory containing files. The output
argument specifies the path of the resulting resource container file.
Repacks a resource container file without unpacking to disk. This command is primarily useful for development of novadrop-rc.
The input
argument specifies the input resource container file. The output
argument specifies the path of the resulting resource container file.
Unpacks the files in a resource container file to a directory.
The input
argument specifies the input resource container file. The output
argument specifies the path of the directory to extract files to.
Verifies the format integrity of a resource container file. This means loading all contained files into memory and verifying that no errors occur.
The input
argument specifies the input resource container file.
This page describes the communication protocol employed by launcher.exe
, Tl.exe
, and TERA.exe
.
C/C++-like primitive types and struct
s will be used.
Integers (uint8_t
, int8_t
, uint16_t
, int16_t
, etc) are little endian.
Characters (i.e. char8_t
and char16_t
) are UTF-8 and UTF-16 respectively, and little endian.
Strings (i.e. u8string
and u16string
) are a series of valid char8_t
and char16_t
characters respectively, followed by a NUL character.
Fields are laid out in the declared order with no implied padding anywhere.
Note that strings are not always NUL-terminated. For this reason, the document will explicitly call out whether a NUL terminator is present.
The role of each program is as follows:
launcher.exe
: The publisher-specific game launcher which performs authentication and server list URL resolution. Serves requests from Tl.exe
and receives game events.
Tl.exe
: The (mostly) publisher-agnostic game launcher which requests authentication data and the server list URL from launcher.exe
. Serves requests and forwards game events from TERA.exe
.
TERA.exe
: The actual game client. Sends requests and game events to Tl.exe
.
These programs all communicate via , specifically . The dwData
field specifies the message ID, while lpData
and cbData
contain the payload pointer and length.
Tl.exe
-> launcher.exe
MessagesMessages sent between Tl.exe
and launcher.exe
consist of text encoded as UTF-8. A NUL terminator is present in most messages, but not all. Responses from launcher.exe
should always use the same message ID that Tl.exe
used in the corresponding request message. Notably, only the Hello Handshake and Game Event Notification messages have a static ID; the request messages use a message counter as the message ID, so the contents must be parsed to understand them.
0x0dbadb0a
)The protocol starts off with a handshake sent from Tl.exe
. This message contains the NUL-terminated string Hello!!
.
0x0
)^csPopup\(\)$
: Signals that launcher.exe
should open the customer support website (e.g. in the default Web browser).
^gameEvent\((\d+)\)$
: Indicates some kind of notable action taken by the user in the game. The value in parentheses is a code specifying the type of event; the possible values are documented in the section on TERA.exe
messages.
^endPopup\((\d+)\)$
: Indicates that the client has exited. The value in parentheses is an exit reason code (not the same as the process exit code); the possible values are documented in the section on TERA.exe
messages.
^promoPopup\(\d+\)$
: The exact purpose of this notification is currently unknown.
launcher.exe
should not respond to these messages.
Tl.exe
will request the server list URL from launcher.exe
. This message does not have a static message ID. The message contains the NUL-terminated string slsurl
.
launcher.exe
should respond with the NUL-terminated server list URL.
gamestr
is only sent when the game is initially launched. This request asks for the full authentication data.
ticket
, last_svr
, and char_cnt
are only sent when returning to the server list from an arbiter server.
ticket
: Requests the authentication ticket. This can be the same ticket as before, but launcher.exe
may also choose to authenticate anew and retrieve a fresh ticket.
last_svr
: Requests the ID of the last server the the account connected to.
char_cnt
: Requests character counts for each server in the server list.
launcher.exe
should respond with the NUL-terminated JSON payload.
Some properties are only required depending on the message:
gamestr
: All properties are required.
ticket
: The ticket
property is required.
last_svr
: The last_connected_server_id
property is required.
char_cnt
: The chars_per_server
property is required.
result-message
, account_bits
, access_level
, and user_permission
are completely optional.
Tl.exe
will request a URL to be opened in the client's embedded Web browser. This message does not have a static message ID and is not NUL-terminated.
The message can be described by the regular expression ^getWebLinkUrl\((\d+),(.*)\)$
. The first group is the ID of a UIWindow
node under the CoherentGTWeb
data center sheet, and the second group is a set of arguments specific to that URL.
launcher.exe
should respond with a URL to be opened (without a NUL terminator), or an empty payload to reject the request.
TERA.exe
-> Tl.exe
MessagesMessages sent between TERA.exe
and Tl.exe
use a simple binary protocol. All messages have static message IDs; responses have different IDs from requests.
0x1
)TERA.exe
will request the (game) account name from Tl.exe
.
0x2
)Tl.exe
should respond with the account name.
account_name
is the name of the game account. It is not NUL-terminated.
0x3
)TERA.exe
will request the session ticket from Tl.exe
.
0x4
)Tl.exe
should respond with the session ticket.
session_ticket
is the authentication session ticket. It is not NUL-terminated.
0x5
)TERA.exe
will request the server list from Tl.exe
.
sorting
specifies how Tl.exe
should sort the server list. Valid values are as follows:
A few notes on sorting:
The sort should be stable.
LAUNCHER_SERVER_LIST_SORT_CRITERIA_NONE
indicates that Tl.exe
is free to sort the list arbitrarily.
The resultant list should be maintained between requests and further sorted on each request, unless LAUNCHER_SERVER_LIST_SORTING_NONE
is sent to reset the sorting.
If the same sorting is requested multiple times and is any sorting other than LAUNCHER_SERVER_LIST_SORT_CRITERIA_NONE
, the list should simply be reversed without applying sorting.
0x6
)Server List Structures
The server list response can be described with the following message definitions:
A few notes on these definitions:
They will not work correctly as proto3
due to required
semantics.
bytes
fields are really u16string
without NUL terminators.
id
must be a positive (non-zero) value.
port
should be in the uint16_t
range.
available
is really a bool
, so only the values 0
and 1
are allowed.
Either address
or host
must be set; not neither and not both.
For address
, a value of 0
has 'not set' semantics since the field is not marked optional
.
sort_criterion
should be the LauncherServerListSortCriteria
value that was sent in the request.
0x7
)TERA.exe
will notify Tl.exe
when entering the lobby (i.e. successfully connecting to an arbiter server) or when entering the world on a particular character.
The two cases can be distinguished by looking at the payload length.
character_name
is the NUL-terminated name of the character that the user is entering the world on.
Create Room (0x8
)
Join Room (0xa
)
Leave Room (0xc
)
Set Volume (0x13
)
Set Microphone (0x14
)
Silence User (0x15
)
These messages were only present in some regions and were likely never actually used. It is currently unknown what their payloads contain.
The following responses exist for the above TeamSpeak requests:
Create Room Result (0x9
)
Join Room Result (0xb
)
Leave Room Result (0xd
)
0x19
)TERA.exe
asks Tl.exe
to open a website in the default Web browser.
id
specifies the kind of website that should be opened. The possible values are currently unknown.
0x1a
)This request is the TERA.exe
equivalent of the request sent by Tl.exe
to launcher.exe
.
id
refers to a UIWindow
node under the CoherentGTWeb
data center sheet.
arguments
specifies the NUL-terminated arguments specific to the URL.
0x1b
)id
is the same value that was sent in the request.
url
is the NUL-terminated URL to open. It can be the empty string or the special string |
to indicate that no URL should be opened.
0x3e8
)TERA.exe
will notify Tl.exe
that it has launched.
source_revision
is the SrcRegVer
value from the client's ReleaseRevision.txt
file.
The meaning of unknown_1
is currently unknown.
windows_account_name
is the NUL-terminated name of the current Windows user account.
0x3e9
- 0x3f8
)TERA.exe
will occasionally notify Tl.exe
of various notable actions taken by the user.
event
specifies the kind of event that occurred. Valid values are as follows:
0x3fc
)TERA.exe
will notify Tl.exe
that it is exiting.
length
is the length of the payload. It must be 12
.
code
is the exit code of the TERA.exe
process. This can be 0
or 1
.
reason
provides a more specific exit reason. Some known values are as follows:
(The above enumeration is an incomplete list.)
0x3fd
)TERA.exe
will notify Tl.exe
that it has crashed (e.g. because of a memory access violation). Note that, since a crash could mean things are arbitrarily broken, this message may not be produced if the crash is sufficiently severe.
details
contains various details about the crash such as the instruction pointer and exception type. It is not NUL-terminated.
0x3fe
- 0x400
)0x3fe
)TERA.exe
will notify Tl.exe
that the anti-cheat module is starting.
0x3ff
)TERA.exe
will notify Tl.exe
that the anti-cheat module has successfully started.
0x400
)TERA.exe
will notify Tl.exe
that the anti-cheat module failed to start.
error
contains the error code from the anti-cheat module.
0x401
)TERA.exe
asks Tl.exe
to open the customer support website in the default Web browser.
0x403
)The exact purpose of this message is currently unknown.
launcher.exe
should respond with a NUL-terminated Hello!!
or Steam!!
to indicate the method of authentication in use. The former uses classic authentication while the latter uses . (Steam authentication will not be documented here.)
Tl.exe
will occasionally notify launcher.exe
of various game events sent by TERA.exe
. The format of these messages can be described with the following :
The Web server at the URL should be prepared to receive an request, potentially with a (which can be ignored). The response should use the . Note that Tl.exe
does not support .
The response received from the server list URL should be in format. It can be described with the following schema:
Tl.exe
will request -encoded authentication data from launcher.exe
. This message does not have a static message ID. The message contains one of several NUL-terminated strings.
The authentication JSON response can be described with the following definition:
Tl.exe
should respond with the server list encoded with .
There is a set of requests for interacting with :
TERA.exe
will notify Tl.exe
of various events relating to the anti-cheat module (e.g. or ). Note that only some regions have a client build with an anti-cheat module.
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--strict
Enables strict format compliance checks while reading the input file.
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--strict
Enables strict format compliance checks while reading the input file.
--encryption-key <key>
Specifies an encryption key (defaults to the latest known key).
--decryption-key <key>
Specifies a decryption key (defaults to the latest known key).
--encryption-key <key>
Specifies an encryption key (defaults to the latest known key).
--strict
Enables strict format compliance checks while reading the input file.