savegame.md 8.5 KB

TirNanoG Saved Game Format

This file is used to store a serialized, compressed game state. It is common on ALL platforms, so for example you can save a game on Windows, and then copy that saved game file to an Android device, and you can load it there, it will work (provided you are using the same game world file too).

All integers are little-endian.

Headers

The file starts with a 32 bytes long file header:

Offset Length Description
0 16 magic, 'TNG Saved Game' + ASCII 10 (newline) + zero
16 16 game id, padded with zeros (may not be zero terminated)

This optionally might be followed by a preview chunk (see below). The preview chunk is not included in the compressed payload.

The header (or the preview chunk) is followed by deflate compressed data and a 4 bytes long CRC checksum. The uncompressed data contains chunks, where all chunk starts with a 8 byte header:

Offset Length Description
0 4 Chunk magic
4 4 Chunk size (including header's size)

Preview Chunk

Magic: PRVW

Offset Length Description
0 4 Chunk magic (PRVW)
4 4 Chunk size (including header's size)
8 4 time spent with playing
12 18 reserved, must be zero
30 2 preview's dimension, must be 256 for now
32 x preview's data

Contains a deflate compressed 15 bit hi-color image with dimensions of 256 x 256, used in the Load Game dialog. Only TirNanoG Player saves this chunk, if the TirNanoG Server sees this, then simply skips it.

Deny List

Magic: DENY

Only saved and loaded by the TirNanoG Server. If the TirNanoG Player sees this chunk, then simply skips it. The header is followed by 17 bytes length records, each with a one byte header. If that byte is 2 (AF_INET), then it is followed by an IPv4 address. If that byte is 10 (AF_INET6), then it is followed by an IPv6 address. Addresses are in network byte order.

Offset Length Description
0 4 Chunk magic (DENY)
4 4 Chunk size (including header's size)
8 n*17 1 byte family, 16 bytes ip address records

Global State

Magic: GLBL

The world's global attributes, serialized integer array, world.numglobals elements.

Offset Length Description
0 4 Chunk magic (GLBL)
4 4 Chunk size (including header's size)
8 n*4 attribute values

Quests

Magic: QSTS

Simple integer array of global quests, with player ids (if quest completed, otherwise -1).

Offset Length Description
0 4 Chunk magic (QSTS)
4 4 Chunk size (including header's size)
8 n*4 completer player ids or -1

User State

Magic: USER

User's data like user name, password hash, current attribute values and current inventory status, etc. If the game was saved by the TirNanoG Player, then there's only one user state chunk. If it was saved by the TirNanoG Server, then there are as many user chunks as registered players. The second part of the block is an entity data block, same as with NPCs.

Offset Length Description
0 4 Chunk magic (USER)
4 4 Chunk size (including header's size)
8 32 password hash
40 8 created date
48 8 last login date
56 8 last logout date
64 8 last seen date
72 2 ISO-639-1 language code
74 1 flags (bit 0: banned)
75 1 world.numchar
76 l user name (zero terminated UTF-8, l bytes)
76+l o character options (o = 4 * world.numchar)
76+l+o 64 equipted objects (32 * uint16_t)
140+l+o 64 player's belt
204+l+o e world entity block (same for NPCs)

Non-Player Characters

Magic: NPC and a zero

NPC serialized attributes, current position, current HP etc.

Offset Length Description
0 4 Chunk magic (NPC\0)
4 4 Chunk size (including header's size)
8 4 NPC type internal id
12 4 spawner internal id
16 e world entity block (same as players')

World entity block: | 0 | 3 | current map | | 3 | 1 | direction | | 4 | 4 | x coordinate on map | | 8 | 4 | y coordinate on map | | 12 | 1 | NPC behaviour (always zero for real players) | | 13 | 1 | transportation method | | 14 | 1 | altitude | | 15 | 1 | number of attributes (a = world.numchrattrs) | | 16 | 2 | number of inventory items (i) | | 18 | 2 | number of skills (s) | | 20 | 2 | number of quests (q) | | 22 | a*4 | 4 bytes attribute value | | 22+a*4 | i*8 | 4 bytes quantity, 4 bytes object id | | 22+a*4+i*8 | s*8 | 4 bytes value (level), 4 bytes object id | | 22+a+i*8+s*8 | q*4 | 4 bytes quest id (bit 31: completed flag) |

Map Objects

Magic: MAP and a zero

Offset Length Description
0 4 Chunk magic (MAP\0)
4 4 Chunk size (including header's size)
8 4 map id
12 n RLE compressed map layer

Only for the "Object" layer and only for maps which were changed by "Replace Object", "Remove Object" or "Add Object" commands.