Skip to content

Commit c76a2b3

Browse files
committed
Added internal docs and a page about the database
1 parent d2a3a38 commit c76a2b3

File tree

5 files changed

+62
-28
lines changed

5 files changed

+62
-28
lines changed

astro.config.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ export default defineConfig({
2727
{label: 'Comparison', slug: 'about/comparison'},
2828
],
2929
},
30+
{
31+
label: "Internal Documentation",
32+
items: [
33+
{label: 'Getting Started', slug: 'internal/getting_started'},
34+
{label: 'Database', slug: 'internal/database'},
35+
],
36+
}
3037
],
3138
favicon: "/favicon.ico",
3239
customCss: [

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: Database
3+
description: Docs for the database system in FerrumC.
4+
---
5+
6+
FerrumC uses the LMDB database for storing data in a key-value format, allowing for fast and efficient data storage and
7+
retrieval. Currently, this is used exclusively for storing chunks, but in the future this will be expanded to store other
8+
data such as player data and entities.
9+
10+
There are several layers of abstraction in place to make working with the database easier. <br/>
11+
Firstly there are some functions in `/src/lib/storage/src/lmdb.rs` that vastly simplify the process of interacting with
12+
the database. These function provide a simple interface for reading and writing data to the database through the use of
13+
functions such as `get()`, `insert()`, `delete()`, and `update()`, etc. Most of these functions work with a 128-bit key,
14+
a table name as a string and an array of bytes as the value. <br/>
15+
Inside most of these functions, tokio is used to spawn a blocking task, relegating the non-async database operations to
16+
a separate task to prevent blocking the main thread. This is done by using the `tokio::task::spawn_blocking()` function.
17+
This does require some ownership shenanigans, hence the Env being wrapped in an Arc and cloned before entering the
18+
blocking task. <br/>
19+
These functions can be used by anything, but does offer a fairly primitive interface. Code needing to interact with the
20+
database should have their own wrappers for handling things like caching or serializing/deserializing data.
21+
22+
There is a second layer of abstract for chunks, found in `/src/lib/world/src/db_functions.rs`. These functions are
23+
specifically for handling chunk data, and provide a more high-level interface for working with chunks.
24+
These functions handle caching, serializing/deserializing, and converting coordinates and the dimension name into a key.
25+
26+
The specifics of caching are covered in a separate section, but the general idea is that chunks are stored in a cache
27+
any time they are read or written, and are removed from the cache when a time or size cap is hit. <br/>
28+
Serializing is currently done using the [bitcode](https://crates.io/crates/bitcode/) crate, which is a simple and
29+
performant way to serialize and deserialize data. This is used to serialize the chunk data into a byte array, which is
30+
then stored in the database, using the aforementioned primitive functions. There is also a compression step used to
31+
decrease the amount of disk space a world takes up<br/>
32+
Generating the key is done in the `create_key()` function, which takes a dimension name, an x coordinate and a z
33+
coordinate and produces a 128-bit key. This key is then used to interact with the database. This key is created by first
34+
hashing the dimension name with [wyhash](https://crates.io/crates/wyhash) and shifting the 64 bit digest into a 128-bit
35+
key as the first 32 bits. The x and z coordinates are then widened to 48-bit integers and shifted into the remaining
36+
96 bits. This ensures that the dimension name has sufficient a keyspace to not risk hash collisions with many dimensions
37+
and the x and z coordinates can be sufficiently large to not limit the world size.<br/>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: Internal documentation
3+
description: Internal documentation for FerrumC's codebase.
4+
---
5+
6+
These pages serve as a guide to the FerrumC codebase, explaining how parts of it work and providing examples of how to
7+
extend it.
8+
9+
Due to the rapidly updating codebase they may not be completely up to date, but you are welcome to suggest edits to these
10+
docs if you notice any discrepancies.

src/content/docs/start/getting_started.mdx

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ This will create a `ferrumc` executable in the `target/release` directory.
183183

184184
3. **Import an existing world**
185185

186-
Place the region files (.mca) in the folder named import then run
186+
Copy the world's files into the `import` directory in the FerrumC directory. This should leave you with some
187+
folders such as "region", "data" and "entities" directly inside the `import` directory.
187188
<Tabs syncKey="os">
188189
<TabItem label="Linux">
189190
~~~bash
@@ -213,15 +214,15 @@ This will create a `ferrumc` executable in the `target/release` directory.
213214
</TabItem>
214215
<TabItem label="macOS">
215216
<FileTree>
216-
- import region files in here
217+
- import world files in here
217218
- ...
218219
- config.toml
219220
- ferrumc
220221
</FileTree>
221222
</TabItem>
222223
<TabItem label="Windows">
223224
<FileTree>
224-
- import region files in here
225+
- import world files in here
225226
- ...
226227
- config.toml
227228
- ferrumc.exe
@@ -266,7 +267,7 @@ This will create a `ferrumc` executable in the `target/release` directory.
266267
~~~
267268
</TabItem>
268269
<TabItem label="Windows">
269-
~~~cmd
270+
~~~bash
270271
.\ferrumc.exe
271272
~~~
272273
</TabItem>
@@ -285,7 +286,7 @@ You can change logging level by using ```--log=<level>```:
285286
~~~
286287
</TabItem>
287288
<TabItem label="Windows">
288-
~~~cmd
289+
~~~bash
289290
.\ferrumc.exe --log=info #for info level logging
290291
~~~
291292
</TabItem>
@@ -298,28 +299,6 @@ You can change logging level by using ```--log=<level>```:
298299
- warn (Only warnings)
299300
- error (Only errors)
300301

301-
<Aside type="tip">
302-
You can specify the directory to treat as the root directory (the place where the config files, data files, etc. live) by setting an environment variable `FERRUMC_ROOT` to the path of the directory.
303-
<Tabs syncKey="os">
304-
<TabItem label="Linux">
305-
~~~bash
306-
export FERRUMC_ROOT=/home/YourUser/Documents/Code/Rust/ferrumc
307-
~~~
308-
</TabItem>
309-
<TabItem label="macOS">
310-
~~~bash
311-
export FERRUMC_ROOT=/home/YourUser/Documents/Code/Rust/ferrumc
312-
~~~
313-
</TabItem>
314-
<TabItem label="Windows">
315-
~~~cmd
316-
set FERRUMC_ROOT=C:\Users\YourUser\Documents\Code\Rust\ferrumc
317-
~~~
318-
</TabItem>
319-
</Tabs>
320-
This is useful if you can't move the place the binary is executed from (`cargo run` for example).
321-
</Aside>
322-
323302

324303

325304
---

0 commit comments

Comments
 (0)