The purpose of this document the WLD file format for Terraria 1.3.x.x . This document will allow anyone with basic programming knowledge to edit and play with the data contained in a WLD file.
This doesn't cover Terraria 1.4 nor Terraria OW nor Terraria 2.
This doesn't cover Terraria 1.2.x.x and below.
Boolean data are saved as bytes (except for the tiles). See BinaryWriter.Write(bool) in C# for more information.
The data described here are valid regarding the save file and may be different from the value stored in the RAM while the game is running (e.g. the bits used to describe a slope).
A WLD file is made of 8 sections. Each section serves a purpose.
The sections are :
Others ressources in this document :
It contains metadata about the file and some specific values used to create the whole file. There is also an index that contains the offset of each other section.
This section starts at the beginning of the file and is 121 bytes wide.
It contains informations about the world, how it was generated and some informations about what happended since its creation.
This part is not fully described.
That's probably for this data that you are reading this document. The whole map as blocks, with every layer (blocks, walls, liquids, furnitures, decorations, paint, wirings, etc.).
The names and contents of each chest.
This part is not covered yet
The text written in each sign.
This part is not covered yet
The names and informations (house location, etc.) about each NPC.
This part is not covered yet
This part is not covered yet
This part is not covered yet
address | Type | Size | Name | Value | Comment |
---|---|---|---|---|---|
0x00 | int | curRelease | see here | ||
0x04 | byte | 7 | magicNumber | see here | |
0x0B | byte | filetype | 2 | ||
0x0C | uint | revision | Incremented every time the file is saved | ||
0x10 | ulong | isFavorite | 0 | It's a boolean encoded on 64 bits. The code always sets it to false | |
0x18 | short | numberOfPointers | 0xA = 10 | ||
0x01A | int | 10 | arrayOfPointers | It's an array that contains the start address of the next section in the file. | |
0x42 | short | numberOfTileFrameImportant | 0x1A3 = 419 | ||
0x44 | bool | 419 | tileFrameImportant | see here |
address | Type | Points to |
---|---|---|
0x1A | int | worldHeader |
0x1E | int | worldTiles |
0x22 | int | chests |
0x26 | int | signs |
0x2A | int | NPCs |
0x2E | int | entities |
0x32 | int | footer |
0x36 | int | unused |
0x3A | int | unused |
0x3E | int | unused |
This section of the file contains informations on the current state of the game (weathers, kills, time, objective accomplished, boss killed, etc.).
This section is not well detailled as lots of informations are yet to be uderstood. At least the architechture is known.
Due to the name of the world being a string of undefinite size all addresses of the following table are relative to the row #3.
# | address | Name (from source code) | Type | Note |
---|---|---|---|---|
1 | @0x0079 | Main.worldNameSize | byte | Those values can be read as one with BinaryReader.Read(String) in c# |
2 | @0x007A | Main.worldName | byte[] | |
3 | 0x0000 | Main.worldID | int | The ID of the world, works as a seed. It is used to name the minimap file .MAP inf the player folder. |
4 | 0x0004 | Main.leftWorld | int | Map dimension in "pixels". Origin is top-left corner. |
5 | 0x0008 | Main.rightWorld | int | |
6 | 0x000C | Main.topWorld | int | |
7 | 0x0010 | Main.bottomWorld | int | |
8 | 0x0014 | Main.maxTilesY | int | Map dimension in tiles. |
9 | 0x0018 | Main.maxTilesX | int | |
10 | 0x001C | Main.expertMode | byte | |
11 | 0x001D | Main.*.CreationTime | int64 | Encoded in a binary format with the C# method DAtetime.ToBinary(). |
12 | 0x0025 | Main.moonType | byte | Not to be confused with the moon phase (see row #36). |
13 | 0x0026 | Main.treeX[0] | int | |
14 | 0x002A | Main.treeX[1] | int | |
15 | 0x002E | Main.treeX[2] | int | |
16 | 0x0032 | Main.treeStyle[0] | int | |
17 | 0x0036 | Main.treeStyle[1] | int | |
18 | 0x003A | Main.treeStyle[2] | int | |
19 | 0x003E | Main.treeStyle[3] | int | |
20 | 0x0042 | Main.caveBackX[0] | int | |
21 | 0x0046 | Main.caveBackX[1] | int | |
22 | 0x004A | Main.caveBackX[2] | int | |
23 | 0x004E | Main.caveBackStyle[0] | int | |
24 | 0x0052 | Main.caveBackStyle[1] | int | |
25 | 0x0056 | Main.caveBackStyle[2] | int | |
26 | 0x005A | Main.caveBackStyle[3] | int | |
27 | 0x005E | Main.iceBackStyle | int | |
28 | 0x0062 | Main.jungleBackStyle | int | |
29 | 0x0066 | Main.hellBackStyle | int | |
30 | 0x006A | Main.spawnTileX | int | |
31 | 0x006E | Main.spawnTileY | int | |
32 | 0x0072 | Main.worldSurface | double | |
33 | 0x007A | Main.rockLayer | double | |
34 | 0x0082 | WorldFile.tempTime | double | |
35 | 0x008A | WorldFile.tempDayTime | byte | |
36 | 0x008B | WorldFile.tempMoonPhase | int | |
37 | 0x008F | WorldFile.tempBloodMoon | byte | |
38 | 0x0090 | WorldFile.tempEclipse | byte | |
39 | 0x0091 | Main.dungeonX | int | |
40 | 0x0095 | Main.dungeonY | int | |
41 | 0x0099 | WorldGen.crimson | byte | |
42 | 0x009A | NPC.downedBoss1 | byte | |
43 | 0x009B | NPC.downedBoss2 | byte | |
44 | 0x009C | NPC.downedBoss3 | byte | |
45 | 0x009D | NPC.downedQueenBee | byte | |
46 | 0x009E | NPC.downedMechBoss1 | byte | |
47 | 0x009F | NPC.downedMechBoss2 | byte | |
48 | 0x00A0 | NPC.downedMechBoss3 | byte | |
49 | 0x00A1 | NPC.downedMechBossAny | byte | |
50 | 0x00A2 | NPC.downedPlantBoss | byte | |
51 | 0x00A3 | NPC.downedGolemBoss | byte | |
52 | 0x00A4 | NPC.downedSlimeKing | byte | |
53 | 0x00A5 | NPC.savedGoblin | byte | |
54 | 0x00A6 | NPC.savedWizard | byte | |
55 | 0x00A7 | NPC.savedMech | byte | |
56 | 0x00A8 | NPC.downedGoblins | byte | |
57 | 0x00A9 | NPC.downedClown | byte | |
58 | 0x00AA | NPC.downedFrost | byte | |
59 | 0x00AB | NPC.downedPirates | byte | |
60 | 0x00AC | WorldGen.shadowOrbSmashed | byte | |
61 | 0x00AD | WorldGen.spawnMeteor | byte | |
62 | 0x00AE | WorldGen.shadowOrbCount | byte | |
63 | 0x00AF | WorldGen.altarCount | int | |
64 | 0x00B3 | Main.hardMode | byte | |
65 | 0x00B4 | Main.invasionDelay | int | |
66 | 0x00B8 | Main.invasionSize | int | |
67 | 0x00BC | Main.invasionType | int | |
68 | 0x00C0 | Main.invasionX | double | |
69 | 0x00C8 | Main.slimeRainTime | double | |
70 | 0x00D0 | Main.sundialCooldown | byte | |
71 | 0x00D1 | WorldFile.tempRaining | byte | |
72 | 0x00D2 | WorldFile.tempRainTime | int | |
73 | 0x00D6 | WorldFile.tempMaxRain | float | |
74 | 0x00DA | WorldGen.oreTier1 | int | |
75 | 0x00DE | WorldGen.oreTier2 | int | |
76 | 0x00E2 | WorldGen.oreTier3 | int | |
77 | 0x00E6 | WorldGen.treeBG | byte | |
78 | 0x00E7 | WorldGen.corruptBG | byte | |
79 | 0x00E8 | WorldGen.jungleBG | byte | |
80 | 0x00E9 | WorldGen.snowBG | byte | |
81 | 0x00EA | WorldGen.hallowBG | byte | |
82 | 0x00EB | WorldGen.crimsonBG | byte | |
83 | 0x00EC | WorldGen.desertBG | byte | |
84 | 0x00ED | WorldGen.oceanBG | byte | |
85 | 0x00EE | Main.cloudBGActive | int | |
86 | 0x00F2 | Main.numClouds | short | |
87 | 0x00F4 | Main.windSpeedSet | float | |
88 | 0x00F8 | Main.anglerWhoFinishedToday.Count | int | |
89 | 0x00FC | Main.anglerWhoFinishedToday[i] | string[row #88] | Each string is 1 byte for length and "length" bytes of char. |
90 | 0x0000 | NPC.savedAngler | byte | |
91 | 0x0001 | Main.anglerQuest | int | |
92 | 0x0005 | NPC.savedStylist | byte | |
93 | 0x0006 | NPC.savedTaxCollector | byte | |
94 | 0x0007 | Main.invasionSizeStart | int | |
95 | 0x000B | WorldFile.tempCultistDelay | int | |
96 | 0x000F | 540 | short | This is a constant |
97 | 0x0011 | NPC.killCount[540] | int[540] | |
98 | 0x0881 | Main.fastForwardTime | byte | |
99 | 0x0882 | NPC.downedFishron | byte | |
100 | 0x0883 | NPC.downedMartians | byte | |
101 | 0x0884 | NPC.downedAncientCultist | byte | |
102 | 0x0885 | NPC.downedMoonlord | byte | |
103 | 0x0886 | NPC.downedHalloweenKing | byte | |
104 | 0x0887 | NPC.downedHalloweenTree | byte | |
105 | 0x0888 | NPC.downedChristmasIceQueen | byte | |
106 | 0x0889 | NPC.downedChristmasSantank | byte | |
107 | 0x088A | NPC.downedChristmasTree | byte | |
108 | 0x088B | NPC.downedTowerSolar | byte | |
109 | 0x088C | NPC.downedTowerVortex | byte | |
110 | 0x088D | NPC.downedTowerNebula | byte | |
111 | 0x088E | NPC.downedTowerStardust | byte | |
112 | 0x088F | NPC.TowerActiveSolar | byte | |
113 | 0x0890 | NPC.TowerActiveVortex | byte | |
114 | 0x0891 | NPC.TowerActiveNebula | byte | |
115 | 0x0892 | NPC.TowerActiveStardust | byte | |
116 | 0x0893 | NPC.LunarApocalypseIsUp | byte | |
0x0894 | Next section of the document | - | This address should be 0xA0A + worldNameSize + sizeof(anglerWhoFinishedToday) |
Each tile is made of several layers and informations. Each tile is saved in up to 13 bytes for each tiles.
Here is the order of each byte of information. BE WARNED, all of those informations are only saved when needed. Sometimes you only need 1 byte for a tile, sometimes you need 13 bytes.
Order | Name | Note | Is present if: |
---|---|---|---|
1 | Flags1 | Flags. See here | Always present, may be the only one. |
1 | Flags2 | Flags, wires and slopes. See here | Flags1 bit 0 |
1 | Flags3 | Flags, actuator and actuated state. See here | Flags2 bit 0 |
1 | Type of tile (LSB) | Wiki (Tile IDs) | Flags1 bit 0 |
1 | Type of tile (MSB) | Flags1 bit 5 | |
1 | FrameX (LSB) | Not much info yet. See here. | tileFrameImportant[Type of tile] |
1 | FrameX (MSB | ||
1 | FrameY (LSB) | ||
1 | FrameY (MSB) | ||
1 | Paint of the tile | No list of ID yet. | Flags3 bit 3 |
1 | Type of wall | Wiki (Wall IDs) | Flags1 bit 2 |
1 | Paint of the wall | No list of ID yet. | Flags3 bit 4 |
1 | Volume of the liquid | 0xFF is a tile full of liquid. I think all values are valid. | Flags1 bit 3 OR Flags1 bit 4 |
1 | RLE LSB | How much strictly identical tiles are coming AFTER this one. | Flags1 bit 6 |
1 | RLE MSB | Flags1 bit 7 |
This byte is always present.
The 4th and 5th bits (bit.4 and bit.3) are used to represent a liquid like this :
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Type of liquid |
---|---|---|---|---|---|---|---|---|
- | - | - | 0 | 0 | - | - | - | No liquid |
- | - | - | 0 | 1 | - | - | - | Water |
- | - | - | 1 | 0 | - | - | - | Lava |
- | - | - | 1 | 1 | - | - | - | Honey |
The 5th, 6th and 7th bits (bit.6, bit.5 and bit.4) are used to represent an altered tile like this :
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Type of alteration |
---|---|---|---|---|---|---|---|---|
- | 0 | 0 | 0 | - | - | - | - | No alteration, tile is a square. |
- | 0 | 0 | 1 | - | - | - | - | Half tile. |
- | 0 | 1 | 0 | - | - | - | - | Slope with top-right corner missing. |
- | 0 | 1 | 1 | - | - | - | - | Slope with top-left corner missing. |
- | 1 | 0 | 0 | - | - | - | - | Slope with bottom-right corner missing. |
- | 1 | 0 | 1 | - | - | - | - | Slope with bottom-left corner missing. |
- | 1 | 1 | 0 | - | - | - | - | unused |
- | 1 | 1 | 1 | - | - | - | - | unused |
If Flags2 is missing, then Flags3 is also missing.
Here are some detailled examples.
Code | Code (decimal) | Version | Notes |
---|---|---|---|
0x47 | 71 | 1.2.0.3.1 | source |
0x4D | 77 | 1.2.2 | source |
0x66 | 102 | 1.2.4.1 | source |
0x9B | 151 | 1.3.0.4 | |
0x9B | 153 | 1.3.0.5 | |
0x9B | 154 | 1.3.0.6 | |
0x9B | 155 | 1.3.0.7 | |
0x9C | 156 | 1.3.0.8 |
This number is used as a long in Terraria.exe because it is a static string.
Be careful as a long value is saved on 8 bytes and the string value is saved on 7 bytes.
A byte that is used to describe the content of each file.
It's a copy of the array tileFrameImportant (used in the game). It is set to true for each tile that is animated (torch, etc.), larger than 1 block (life crystal, etc.), has alternative sprite (altars [demon/crimson], table (wood/boreal/cactus/...], etc.).
Here are the value of this array as bytes[53] instead of bool[419]. This can be read as an array of 424 bits (the last 5 bits being unused) or 53 bytes.
The data of tileFrameImportant should be used as bits instead of bytes for convenience.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x38 | 0xFC | 0x3F | 0xBD | 0x1E | 0x04 | 0x84 | 0x20 | 0x80 | 0xE7 | 0xFE | 0xFF | 0xFF | 0x47 | 0x06 | 0x60 |
0xF3 | 0xEF | 0x21 | 0x00 | 0x20 | 0x78 | 0x04 | 0x0F | 0x00 | 0x82 | 0x96 | 0x1F | 0x98 | 0xFA | 0xFF | 0x40 |
0x00 | 0xE0 | 0xF8 | 0xEF | 0xFF | 0xFF | 0x7F | 0xF4 | 0x19 | 0xC0 | 0x0E | 0x20 | 0xDC | 0x1F | 0xF0 | 0x17 |
0xFC | 0x0F | 0x60 | 0x7C | 0x00 | - | - | - | - | - | - | - | - | - | - | - |