Revision as of 09:46, 5 October 2024 by Librae (talk | contribs)

Development:Structure

From librae wiki

This article describes the structure of the code of Librae. [The code itself is available on GitLab https://gitlab.com/librae/librae].

Part of the game engine is called rustorion. It's the older name for the project, and intended to be the name of the engine, when it is fully separated from game logic.

Language

The game is written in Rust. It tries to be pure Rust, but some unique foreign components are still used, most prominently GTK4 for the user interface.

Main parts

  • rustorion — game logic library
  • librae-gui — gtk-based UI
  • librae-cli — CLI tools

Game state

The game is structured to support trustless (except the server), simultaneous multiplayer. The game state is stored as a single universe structure (rustorion::Universe). Client receives a view which contains only the information the client is supposed to know. Client sends actions to the server that contain the information about what the client wants to do on the current turn. When all the players are ready (submitted their actions or it's a timeout), the server processes all the actions (they are designed to be executed independently of each other, so there are no race conditions), performs various updating on the universe and notifies clients that they can download new views.

In the future, clients might be able to download previous views to browse them at will or use for gathering statistics.

Entities and IDs

Most things, entities within the universe, or anything else that implements EntityStored have an ID. It is an unique identifier of an entity within the storing structure. Using EntityStored::get() and other similar methods you can obtain a reference to the entity by its ID. IDs are used to store links between entities through plain inclusion on a structure, or using types from rustorion::storage::links for more complex relations like many-to-many.

IDs are issued sequentially, but then the number is encrypted with Blowfish to ensure there is no leaking information about number of entities in an universe. Because the encryption key is stored in Universe, only Universe can issue new IDs.

Working with state

To modify the state, the only option is to work with the storage type (e.g. Universe) directly. However, this is not easy, you have to obtain IDs, use them to extract data, etc., manually. This appears to be the only way to keep the structure mutable and avoid using some kind of GC.

However, there are simplified interfaces for Universe and Universeview called rustorion::universe::interface::Universe and rustorion::universeview::interface::Universeview, respectively. These allow for object-oriented, safe examination of data and contain many useful routines. The intention is to use these to prepare the modifications, and later execute them on the storage type after dropping the interface.