Repository navigation
worldMap
Files containing the minimap images / world map. One file is one tile of one zoom level of one cube face, and the set of tiles that belongs to a zone is listed in the worldDir.
Tiles are named {cubemapId}_{zoomLvl}_{entryId}_opt.worldMap, with the zoom level padded to
two digits and the entry id to ten. When the .worldDir has isDataEmbedded set, the exact
same bytes live inside the .worldDir instead of in a file of their own.
- worldMap.bt - the container
- worldMap.payload.bt - run this on the inflated payload
- Reader has been implemented in FauFau: WorldMap.cs. It reads compressed and inline payloads and splits the payload into its layers.
Little endian. After the magic and the version, the file consists of layers like the ones of
the zone, without the marker: a uint32 layer id and a uint32 length.
| Field | Type | Notes |
|---|---|---|
magic |
char[4] |
GTNO |
version |
uint32 |
2 |
layerId |
uint32 |
0, the general layer |
layerLength |
uint32 |
45 |
entryId |
uint32 |
Third part of the file name |
zoomLvl |
uint32 |
Second part of the file name |
originX |
float |
X of the tile's corner |
originY |
float |
Y of the tile's corner |
size |
float |
Edge length of the tile |
boundsMin |
float[3] |
|
boundsMax |
float[3] |
|
compressed |
uint8 |
1 when the payload is in a compressed layer |
The worldDir tile record carries the same nine floats, with the bounds first.
When compressed is set, the compressed layer follows:
| Field | Type | Notes |
|---|---|---|
layerId |
uint32 |
100, the compressed layer |
layerLength |
uint32 |
8 + payloadCompressedSize |
payloadExtractedSize |
uint32 |
Inflated size |
payloadCompressedSize |
uint32 |
Size of the zlib stream, including its 2 byte header |
payload |
byte[] |
zlib stream |
Otherwise the payload follows the general layer as it is, up to the end of the file.
An older version of this page read the version and the general layer header as int32[3], named
entryId and zoomLvl "last" and "second" (after the parts of the file name they correspond
to), and had a lodSubsectionId of 25601 and an unknown byte after the floats. 25601
(0x6401) is the compressed byte followed by the first three bytes of the layer id 100,
the unknown byte is the last byte of that id, and the old dataLength is the layer length.
The payload is a flat chunk stream that runs to the end of the buffer. Every chunk is:
| Field | Type |
|---|---|
id |
uint32 |
length |
uint32 |
data |
byte[length] |
Known ids:
| Id | Contents |
|---|---|
| 10 | Diffuse texture |
| 11 | Normal texture |
| 21 | Vertices. uint32 count then count 24 byte records of half floats and shorts |
| 31 |
uint32 total, uint32 splitAt, one padding byte, then two runs of ushort v1, v2, v3 faces, the first splitAt / 3 long and the second (total - splitAt) / 3 long |
| 41 |
uint32 count, one padding byte, then count / 2 records of ushort offset, ushort count, where each count is a number of triples of shorts |
| 50 | Not decoded |
| 61 |
uint32 count then count 13 byte records, followed by uint32 n and n shorts |
The chunk ids are stable across the files looked at. 10 and 11 being the diffuse and normal texture, 21 the vertices and 31 and 41 indices is what FauFau goes by, the layouts of 31, 41 and 61 come from reading the shapes in a hex editor rather than from the client, so treat them as a starting point. Nothing here has been rendered back to a picture yet, which is the obvious way to confirm them.
Chunks 10 and 11 are the actual map imagery, and are the interesting ones for anyone wanting to extract the world map.