Skip to content

Database

The game stores all data in a save folder with RocksDB database. This does not include data such as assets or Lua files. A single "save" is defined as an entire RocksDB database folder.

What does the database store?

  • Galaxy systems, sectors, planets
  • Player information
  • Entity locations (not realtime)
  • Inventories
  • Currencies
  • Anything that we need to load that is not an asset

Why a database?

Why do we need a database in a game?

The universe is persistent and we need to store the data somewhere. When you warp out of a sector the state of that sector is saved. When you warp back to that sector the state is loaded and restored back.

There are many ways how a game can store a data. Many games use their own formats. We can use JSON files. We can use SQL. There are infinite options.

The Temporary Escape uses a document database because of the following reasons:

  • Document store database does not use a schema, which allows for easier modding.
  • We can store small and large data very efficiently with RocksDB.
  • It's very fast.
  • Embedded, it is part of the game engine and not as a separate program.

Where is the database stored?

PlatformPath
WindowsC:\Users\YOUR_USERNAME\AppData\Roaming\Temporary Escape\Saves\SAVE_NAME\
Linux~/.temporary-escape/Saves/SAVE_NAME/
MacOS~/Library/Application Support/Temporary Escape/Saves/SAVE_NAME/

Document style

The RocksDB database is a key-value database but has been modified to work as a document database with indexes. This is a custom made database logic that is part of the game engine. You can think of a document as a collection of some values with keys that have values. Such values can have nested documents.

A simplified example of a galaxy system represented as JSON would be:

json
{
  "name": "Intra",
  "pos": [
    83.75674,
    -23.2574
  ],
  "seed": 125596117633147,
  "galaxyId": 1,
  "regionId": 7,
  "factionId": null
}

Please note that documents are not stored as a JSON in the database, instead they use CBOR serialization. More on that later.

Accessing via Lua scripts

To access the database (read, modify, write, delete) you can do so through any Lua script.

All data in the database is accessed via Lua types such as tables, strings, numbers, etc. Never classes.

The database instance can be accessed by server.db inside any Lua script. The db is a member of server, and the server is globally defined. Also note that any operation on such db database instance is done via self, therefore you need to call functions via the : syntax!

Database operations

There are many database operations. The basic are:

There are also few special operations such as:

You can also iterate over

Insert a new document

The following example below inserts a new document of name Example and prints the unique ID of the document. An insert always produces a new document ID!

lua
-- `server` is globally defined! and `server.db` is a database instance! 
local id = server.db:insert("Example", {
    foo = "hello",
    bar = 42,
    nested = {
        a = true,
        b = nil,
    },
})

logger:info("Inserted example id: %d", id)

Using non-table types is also valid, example below:

lua
local id0 = server.db:insert("Example", "Hello World!")
local id1 = server.db:insert("Example", true)
local id2 = server.db:insert("Example", nil)

Get a document

Getting a document is done by its numerical ID.

If the document does not exist then a nil is returned.

lua
local id = server.db:insert("Example", {
    msg = "Hello World!"
})

local doc = server.db:get("Example", id)
logger:info("Document msg: %s", doc.msg)
-- Prints: "Document msg: Hello World!"

Delete a document

Deleting a document is similar as getting it. You use the document numerical ID.

Deleting a document that does not exist produces NO error. This also means that deleting the same document multiple times is valid (the document is deleted only once).

lua
local id = server.db:insert("Example", {
    msg = "Hello World!"
})

server.db:remove("Example", id)

local doc = server.db:get("Example", id)
logger:info("Document is nil: %s", doc == nil)
-- Prints: "Document is nil: true"

Update an existing document

Upsert (insert or update)

Seek (iterating multiple keys)

Database indexes

Seek by index

Transactions

Example: explore a system

Database in details (optional)

TIP

This is an in-depth explanation of how the database is organized internally. You do not need to understand this part in order to create mods!

Keys

Keys are not stored in the document. Keys are stored only by the database with the key-value pairs.

Example of a key:

docs:Systems:{id}

The key starts with a 4-character prefix. The docs means that the value is a document. The : is used as a separator. The System is the name of the document (you could think of it as a namespace, or a table name).

And lastly, the {id} is an 64-bit integer in BIG endian order. This is a unique ID of the document. However, differently named documents can share the same ID. The ID is only unique between the same document names.

CBOR format