### Disclaimer This documentation is generated by IA, it's purely based on the current code and is reviewed by me before commiting, so I can ensure it respect your reading time and contains meaningful information # Project Architecture This document outlines the architecture of the project, with a focus on the Entity-Component-System (ECS) design of both the client and server. ## Client The client is responsible for rendering the world and handling user input. It connects to the server to get the world data and send player actions. ### Plugins and Systems The following plugins are used to organize the client's systems: - **[`CameraControllerPlugin`](./crates/client/src/controller/camera_controller.rs#L9)**: Manages camera switching and mouse grabbing. - [`switch_camera`](./crates/client/src/controller/camera_controller.rs#L105): Switches between `FlyBy` and `FirstPerson` cameras. - [`grab_mouse`](./crates/client/src/controller/camera_controller.rs#L115): Grabs or releases the mouse cursor. - **[`CharacterControllerPlugin`](./crates/client/src/controller/character_controller.rs#L6)**: Manages character movement and position updates. - [`move_character`](./crates/client/src/controller/character_controller.rs#L60): Moves the character based on keyboard input. - [`update_character_position`](./crates/client/src/controller/character_controller.rs#L115): Updates the character's position in the world. - **[`DebugPlugin`](./crates/client/src/debug/mod.rs#L3)**: Adds debugging functionalities. - [`setup_hold_est_to_exit`](./crates/client/src/debug/mod.rs#L18): Initializes the `EscHolding` resource. - [`hold_esc_to_exit`](./crates/client/src/debug/mod.rs#L22): Exits the application when the `Esc` key is held down. - **[`NetPlugin`](./crates/client/src/net.rs#L14)**: Handles the connection to the server and incoming messages. - [`reconnect_to_server`](./crates/client/src/net.rs#L41): Tries to reconnect to the server if the connection is lost. - [`server_connection`](./crates/client/src/net.rs#L69): Establishes the initial connection to the server. - [`handle_messages`](./crates/client/src/net.rs#L91): Processes incoming messages from the server. - **[`MeshingPlugin`](./crates/client/src/set/meshing.rs#L14)**: Generates the chunk meshes. - [`update_chunk_mesh`](./crates/client/src/set/meshing.rs#L36): Updates the mesh of a chunk when new vertex data is received. - [`despawn_chunks_on_server_disconnect`](./crates/client/src/set/meshing.rs#L25): Despawns all chunks when the server disconnects. - **[`ReceiveMessagesPlugin`](./crates/client/src/set/receive_messages.rs#L3)**: This plugin is currently empty. - **[`SendInputPlugin`](./crates/client/src/set/send_input.rs#L5)**: Sends player input to the server. - [`update_player_landscape`](./crates/client/src/set/send_input.rs#L30): Sends a `LandscapeUpdate` message to the server when the player's landscape changes. - [`send_welcome_message`](./crates/client/src/set/send_input.rs#L37): Sends a `LandscapeUpdate` message to the server when the client connects. ### System Sets (ClientSet) The client's systems are organized into the following `SystemSet`s, which are executed in a specific order: 1. **`PreUpdate`**: - `ReceiveMessages`: - `reconnect_to_server` (`NetPlugin`) - `server_connection` (`NetPlugin`) - `handle_messages` (`NetPlugin`) 2. **`Update`**: - `Meshing`: - `update_chunk_mesh` (`MeshingPlugin`) - `despawn_chunks_on_server_disconnect` (`MeshingPlugin`) 3. **`PostUpdate`**: - `SendInput`: - `update_player_landscape` (`SendInputPlugin`) - `send_welcome_message` (`SendInputPlugin`) ## Server The server is responsible for managing the game world, including world generation, chunk management, and processing player actions. ### Plugins and Systems The following plugins are used to organize the server's systems: - **[`ChunkAssetPlugin`](./crates/server/src/asset.rs#L24)**: Manages the loading and generation of chunk assets. - **[`NetPlugin`](./crates/server/src/net.rs#L13)**: Handles client connections and messages. - [`start_network_server`](./crates/server/src/net.rs#L36): Starts the network server. - [`new_client_connected`](./crates/server/src/net.rs#L66): Handles new client connections. - [`remove_disconnected_clients`](./crates/server/src/net.rs#L53): Removes disconnected clients. - [`handle_messages`](./crates/server/src/net.rs#L78): Processes incoming messages from clients. - **[`ReceiveRequestsPlugin`](./crates/server/src/set/receive_requests.rs#L13)**: Handles requests from clients. - [`handle_landscape_update`](./crates/server/src/set/receive_requests.rs#L21): Handles the `LandscapeUpdate` message from clients. - **[`LandscapePlugin`](./crates/server/src/set/landscape.rs#L8)**: Manages the game world's landscape. - [`update_landscape`](./crates/server/src/set/landscape.rs#L26): Updates the landscape based on the `Landscape` resource. - **[`ChunkManagementPlugin`](./crates/server/src/set/chunk_management.rs#L13)**: Manages the loading, unloading, and spawning of chunks. - [`chunks_unload`](./crates/server/src/set/chunk_management.rs#L43): Unloads chunks that are no longer needed. - [`chunks_load`](./crates/server/src/set/chunk_management.rs#L61): Loads new chunks. - [`chunks_spawn`](./crates/server/src/set/chunk_management.rs#L76): Spawns new chunks. - **[`PropagationPlugin`](./crates/server/src/set/propagation.rs#L13)**: Propagates light through the world. - [`propagate_light`](./crates/server/src/set/propagation.rs#L31): Propagates light based on `LightUpdate` events. - **[`MeshingPlugin`](./crates/server/src/set/meshing.rs#L11)**: Generates the chunk meshes. - [`faces_occlusion`](./crates/server/src/set/meshing.rs#L30): Calculates the occlusion of chunk faces. - [`faces_light_softening`](./crates/server/src/set/meshing.rs#L73): Softens the light on chunk faces. - [`generate_vertices`](./crates/server/src/set/meshing.rs#L114): Generates the vertices for the chunk meshes. - **[`SendResponsesPlugin`](./crates/server/src/set/send_responses.rs#L10)**: Sends responses to clients. - [`notify_chunk_vertex_updated`](./crates/server/src/set/send_responses.rs#L21): Notifies clients when a chunk's vertices have been updated. ### System Sets (WorldSet) The server's systems are organized into the following `SystemSet`s, which are executed in a specific order: 1. **`PreUpdate`**: - `ReceiveRequests`: - `new_client_connected` (`NetPlugin`) - `remove_disconnected_clients` (`NetPlugin`) - `handle_messages` (`NetPlugin`) - `handle_landscape_update` (`ReceiveRequestsPlugin`) 2. **`Update`**: - `LandscapeUpdate`: - `update_landscape` (`LandscapePlugin`) - `ChunkManagement`: - `chunks_unload` (`ChunkManagementPlugin`) - `chunks_load` (`ChunkManagementPlugin`) - `chunks_spawn` (`ChunkManagementPlugin`) - `Propagation`: - `propagate_light` (`PropagationPlugin`) - `Meshing`: - `faces_occlusion` (`MeshingPlugin`) - `faces_light_softening` (`MeshingPlugin`) - `generate_vertices` (`MeshingPlugin`) 3. **`PostUpdate`**: - `SendResponses`: - `notify_chunk_vertex_updated` (`SendResponsesPlugin`) ## `proto` Crate The `proto` crate is responsible for the communication protocol between the client and the server. It defines the messages that can be sent and received, and it handles the serialization and deserialization of these messages. ### `message_source` Macro The `message_source` macro is the core of the `proto` crate. It takes an enum definition and generates the necessary code to handle the serialization, deserialization, and handling of the messages defined in the enum. The macro generates a simplified version of the enum, a struct for each enum variant, and the necessary trait implementations. ### Traits - **`MessageType`**: This trait is implemented for the simplified enum generated by the `message_source` macro. It defines the methods required to handle the messages, such as getting the message code, serializing and deserializing the message, and running the message handlers. - **`Message`**: This trait is implemented for the structs generated by the `message_source` macro. It defines the methods required to get the message type and source. - **`NoCopy`**: This marker trait is used to indicate that a message should not be copied when handled. This is useful for messages that contain large amounts of data, such as the `ChunkVertex` message. ### Type Erasure Type erasure is used to handle the messages in a generic way. The `message_source` macro generates a `BoxedMessage` type alias, which is a boxed trait object of the `Message` trait. This allows the messages to be stored in a collection and handled without knowing their concrete type. ### Adding a New Message To add a new message, you need to add a new variant to the `ClientMessage` or `ServerMessage` enum in the `messages` crate. The `message_source` macro will automatically generate the necessary code to handle the new message. For example, to add a new `MyMessage` message, you would add the following to the `ClientMessage` enum: ```rust #[message_source(MessageSource::Client)] enum ClientMessage { // ... MyMessage { a: u32, b: bool }, } ``` Then, you need to add a handler for the new message. The handler is a system that takes the message as a parameter using the `In` system param. For example: ```rust fn handle_my_message(In(message): In) { // ... } ``` Finally, you need to register the message handler in the client or server app: ```rust app.add_message_handler(handle_my_message); ```