.tmod File format - tModLoader/tModLoader GitHub Wiki

tModLoader saves mod files in a custom format denoted with a .tmod extension. This file is produced once tModLoader compiles a mod, and it includes the mod assemblies, resources (such as images or sounds), libraries and any other miscellaneous data the modder chose to include within their mod.

The file format is relatively simple, and its layout has been described below. Note: Each data element has been written with its corresponding BinaryReader.ReadX method. If you are writing a .tmod file parser in a language not in .NET, remember that the strings are saved like so:

Value Data Description
Length 4 bytes This is a 7-bit encoded integer describing the length of the string. Search up 7-bit encoded ints if you are unfamiliar with them
String [Length] bytes The actual UTF-8 string, consisting of [Length] bytes

From here on out, any mention of string will refer to the layout above.

Structure of a .tmod binary file:

Value Data BinaryReader method Description
Header 4 bytes BinaryReader.ReadBytes(4) The first 4 bytes of the file are ASCII characters which spell out 'TMOD'. If the header is invalid, then the file isn't a .tmod file / it's corrupt
Version String BinaryReader.ReadString() The version of tModLoader that the mod has been built for
Hash 20 bytes BinaryReader.ReadBytes(20) The SHA1 computed hash of the .tmod file
Signature 256 bytes BinaryReader.ReadBytes(256) The signature of the .tmod file, used by the mod browser
File data length Unsigned 32-bit integer BinaryReader.ReadUInt32() The amount of bytes left in the file after all the previous data has been read. Those remaining bytes are used in computing the hash found earlier in the .tmod file
Mod name String BinaryReader.ReadString() The internal name of the mod stored in the .tmod file
Mod version String BinaryReader.ReadString() The version of the mod stored in the .tmod file
File count Signed 32-bit integer BinaryReader.ReadInt32() The amount of files stored inside the .tmod file
[File count] file entries String, Signed 32-bit int, Signed 32-bit int BinaryReader.ReadString(); BinaryReader.ReadInt32(); BinaryReader.ReadInt32() The string is the name of the file, including its path. The first int is the uncompressed length of the file in bytes, the second int is the compressed length of the file in bytes. Repeat reading the file entries [File count] amount of times to get them all
[File count] file data [File entry compressed length] bytes BinaryReader.ReadBytes([File entry compressed length]) This is where all the actual file data is stored (in the same respective order as the file entries). Each file entry's compressed data length represents the amount of bytes you need to read in order to obtain its data. For example, if the first file entry has a compressed length of 34 bytes, read 34 bytes to get its data. Then if the second has a length of 89, read 89 bytes. Repeat doing this until you reach the end of the .tmod file

Having successfully parsed the .tmod file, you now need to decompress each file's data as tModLoader typically compresses most of the files using the DEFLATE algorithm. (If you're on .NET, a particularly good library for decompressing the data would be Ionic.Zlib). A file is considered compressed if the file entry it is associated with has an unequal compressed length and uncompressed length.