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.
