TirNanoG Admin Protocol
=======================

This is used to communicate with the TirNanoG Server for administrative purposes. See the [TirNanoG MMORPG Protocol](protocol.md)
if you're interested in the actual game's protocol. The main purpose of this interface is to provide integration with your
MMORPG's website, so that you can use a web interface for administering your world or to provide a webshop for your players if
you want to. To ease integration with your site, an example PHP Class is provided in [admin.php](admin.php).

This interface is implemented over an SSL/TLS TCP channel via a REST API, that answers with JSON strings. The HTTP request
headers are only parsed for the first line, and only for the URL and query string part. Only `GET` method requests are accepted.
For security reasons, its access is limited to the IP address specified on the server's command line with the `-a` flag (which,
if the TirNanoG Server is running on the same machine as your website's HTTP server, should be `127.0.0.1` or `::1`).

***IMPORTANT!!!*** The REST API is only available if the `-a` flag was given and you're connecting from that IP address,
otherwise all you'll get is 404. Also note that the REST API uses a self-signed certificate, that web-browsers usually don't like.

Get Server Status
-----------------

Request: `/status`

Response: one object with the following fields:

| Field    | Description                         |
|----------|-------------------------------------|
| `now`    | server's current time               |
| `uptime` | server uptime in seconds            |
| `saved`  | last time when the state was saved  |
| `users`  | number of currently connected users |
| `total`  | number of registered users          |
| `reg`    | true if new users can register      |

Returns the TirNanoG Server's status.

Note: all date and time fields are simple integer numbers containing UTC UNIX timestamps. You can convert that to any timezone
and format it to any localized date time string.


Get World File Details
----------------------

Request: `/tng`

Response: one object with the following fields:

| Field      | Description                         |
|------------|-------------------------------------|
| `gameid`   | game id                             |
| `rev`      | boundled asset's format revision    |
| `type`     | either "ortho" or "iso"             |
| `id`       | game id                             |
| `tilew`    | tile width                          |
| `tileh`    | tile height                         |
| `mapsize`  | map size in tiles (N x N)           |
| `atlaswh`  | sprite atlas size (N x N)           |
| `freq`     | audio frequency                     |
| `fps`      | desired frame per second            |
| `numact`   | number of default action handlers   |
| `numlyr`   | number of map layers                |
| `numtrn`   | number of transportation methods    |
| `maxbc`    | largest functionid used in bytecode |
| `deltay`   | player's sprite Y hotspot           |
| `numlang`  | number of translation dictionaries  |
| `numtext`  | number of translated texts          |
| `numspc`   | number of translated speech audio   |
| `numfont`  | number of fonts                     |
| `nummusic` | number of background music files    |
| `numsound` | number of sound effect files        |
| `nummovie` | number of movie files               |
| `numchr`   | number of chooser menus             |
| `numcut`   | number of cutscenes                 |
| `numnpc`   | number of NPC types                 |
| `numswr`   | number of NPC spawner types         |
| `numdlg`   | number of conversation dialogs      |
| `numcft`   | number of crafting dialogs          |
| `numqst`   | number of quests                    |
| `nummap`   | number of maps                      |
| `numobj`   | number of object types              |

Returns the decoded game world file's fields. Most of these are only informative, and used by the clients to determine wether
they can cope with the game running on the server they're trying to connect to, and not really useful on your website. But just
in case, here it is.


Synchronize to Storage (Save Game)
----------------------------------

Request: `/sync`

Response: an object with a single `ret` field that's either true (success) or false (unable to save game)

This will make the server to save the game's state to storage. It only works if the server was started with the `-s` option,
otherwise it will always return false.


Disable Public User Registration
--------------------------------

Request: `/regoff`

Response: an empty object

Only user names added by the admin are accepted on character generation, see "Add User" below.


Enable Public User Registration
-------------------------------

Request: `/regon`

Response: an empty object

Any user name accepted.


Get List of Registered Users
----------------------------

Request: `/users`

Response: an array of objects with the following fields:

| Field      | Description                         |
|------------|-------------------------------------|
| `username` | user name                           |
| `enabled`  | true if user can log in             |
| `online`   | true if user is currently logged in |


Add User
--------

Request: `/add?u=(user name)`

Response: an object with a single `ret` field that's either true (success) or false (user name already exists)

When registration is on, then any user name is accepted, otherwise only the names that were apriori added by the admin with
this command. This can be used if you want to force user registration on the MMORPG's website rather than allowing it on the
client, where only user name and password is queried. In this set up the users must register on the website first, probably
with a more sophisticated form and multiple fields, and only after that can they create a character with the TirNanoG client.
Note: your website is responsible to save and store the additional user data (in an SQL table for example).


Authenticate User
-----------------

Request: `/auth?u=(user name)&p=(password)`

Response: one object with the following fields:

| Field  | Description                                                       |
|--------|-------------------------------------------------------------------|
| `ret`  | either true (password match) or false (bad user name or password) |
| `lang` | the language code used with the last login                        |

This can be used to authenticate users on your website with the same password that they use to log in with the TirNanoG
client. Useful if you want to provide a forum or webshop for your users. Note: this does not log in the user to the game,
it just *simply checks if the given password is correct or not*.

If the authentication was successful (`ret` is true), then an additional field `lang` also returned. This is the two letter
ISO-639-1 language code that the user used when he/she last logged in with the TirNanoG client. You can use this to set the
default language of the MMORPG website's session, so that the user can see the website's content in his/her own language.


Set Password
------------

Request: `/pass?u=(user name)&p=(password)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)

Useful if you want to implement a "Forgotten password" or a "Change password" feature on your website. Note: this is a
low-level interface, it **does not check anything**. You should show a webform towards the user with three input fields
(the old password and the new password twice), and in the background first call "Authenticate User" to see if the old
password matches, check if the two new passwords are the same and only if so call this API to actually change the user's
password (see the `ChangePassword` method in [admin.php](admin.php) for an example).


Forcefully Logout User from the Game
------------------------------------

Request: `/kick?u=(user name)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)

This will kick out a user from the game.


Ban User
--------

Request: `/ban?u=(user name)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)

This will also kick out the user from the game, but it will also prevent them from re-login.


Unban User
----------

Request: `/unban?u=(user name)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)

Enable login of a specific user again.


Get List of Denied IP Addresses
-------------------------------

Request: `/denied`

Response: an array of strings with the IP addresses

Clients from these IP addresses cannot login, and cannot communicate with the server at all.


Add to Denied List
------------------

Request: `/deny?u=(user name)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)

Adds the given user's last used IP address to the list. Note: you cannot directly query which IP belongs to which user,
and this is deliberate to comply with GDPR.


Remove from Denied List
-----------------------

Request: `/allow?u=(user name)`
   *or*
Request: `/allowip?u=(ip address)`

Response: an object with a single `ret` field that's either true (success) or false (no such user / ip address)

Removes the user's last used IP address (or a specific IP address) from the deny list.


Get User's Status
-----------------

Request: `/user?u=(user name)`

Response: one object with the following fields:

| Field        | Description                                |
|--------------|--------------------------------------------|
| `online`     | true if user is online                     |
| `created`    | time of registration                       |
| `logind`     | time of last login                         |
| `logoutd`    | empty if user is currently online          |
| `lang`       | the language code used with the last login |
| `map`        | name of the map where the player located   |
| `x`, `y`     | coordinates on map                         |
| `dir`        | facing direction                           |
| `transport`  | transport method                           |
| `banned`     | true if user is banned                     |
| `denied`     | true if user's last IP is denied           |
| `charopts`   | an object with name value pairs            |
| `attributes` | an object with name value pairs            |

Note: all date and time fields are simple integer numbers containing UTC UNIX timestamps. The `charopts` field contains
the data that the user entered on the "Character Generation" window, might be empty. The `attributes` field on the other
hand contains the all the dynamically changing properties, and depending on the game, this might be empty too.

The map coordinates aren't real floating point numbers, instead `(tile).(pixel)`. So if your world's tile size is 32, then
the frictional part can go from 0 to 31, because it is in pixels. The direction can be one of `S` (South), `SW` (South-West),
`W` (West), `NW` (North-West), `N` (North), `NE` (North-East), `E` (East), `SE` (South-West). Transport method can be one
of `walk`, `swim`, `fly`.

The `charopts` field is an object with attributes, and its values look like floating point numbers, but they're not. The
integer part represents the actual option choosen, and the frictional part the palette variation for that option.


Set User's Attribute
--------------------

Request: `/set?u=(user name)&(attribute)=(value)`

Response: an object with a single `ret` field that's either true (success) or false (no such user or no such attribute)

Changes the value of a user's attribute. The available `attribute` options depend on the game file.


Get User's Inventory
--------------------

Request: `/inv?u=(user name)`

Response: an array of objects with the following fields:

| Field      | Description                         |
|------------|-------------------------------------|
| `qty`      | quantity                            |
| `obj`      | internal id of the object           |


Get User's Skills
-----------------

Request: `/skills?u=(user name)`

Response: an array of objects with the following fields:

| Field      | Description                         |
|------------|-------------------------------------|
| `level`    | value of the skill                  |
| `obj`      | internal id of the skill            |

Skills are special, virtual "objects" that the players can use. In a fantasy world, these are most likely magic spells.


Get User's Quests
-----------------

Request: `/quests?u=(user name)`

Response: an array of objects with the following fields:

| Field      | Description                         |
|------------|-------------------------------------|
| `completed`| flag                                |
| `qst`      | name of the quest                   |

Returns the player's (ongoing or completed) quests.


Add Item to User
----------------

Request: `/give?u=(user name)&q=(quantity)&o=(object)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)

Note: `object` can be either an object id of an inventory object or of a skill.

Take Item from User
-------------------

Request: `/take?u=(user name)&q=(quantity)&o=(object)`

Response: an object with a single `ret` field that's either true (success) or false (no such user)


