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?
Platform | Path |
---|---|
Windows | C:\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:
{
"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!
-- `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:
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.
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).
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.