Custom Subsystems & Events - Stars-Beyond/Horizon-Community-Edition GitHub Wiki

Custom Subsystems and Events in Horizon

This section guides you through the process of adding your own custom event to a custom subsystem in the Horizon Game Server.

Step-by-Step Guide

  1. Create Your Custom Subsystem

    First, create a new module for your custom subsystem. For this example, let's create a subsystem called custom_subsystem.

    mkdir src/subsystems/custom_subsystem

    Create a new file mod.rs in the custom_subsystem directory:

    touch src/subsystems/custom_subsystem/mod.rs

    Add the following basic structure to your mod.rs file:

    use crate::define_event;
    
    pub fn init(socket: SocketRef) {
        // Initialize your custom subsystem here
        define_event!(socket, "custom_event", custom_event_handler);
    }
    
    async fn custom_event_handler(socket: SocketRef, data: Value) {
        // Handle your custom event here
        println!("Custom event received: {:?}", data);
    }
  2. Update the Main File to Include Your Custom Subsystem

    In your subsystems/mod.rs file, add your custom subsystem module:

        pub mod chat;
        pub mod game_logic;
        pub mod leaderboard;
        pub mod level_data;
        pub mod logging;
        pub mod notifications;
        pub mod player_data;
        pub mod startup;
    
        // Add this line to include your custom subsystem
        pub mod custom_subsystem;

    Update the on_connect function to initialize your custom subsystem:

    fn on_connect(socket: SocketRef, Data(data): Data<Value>, players: Arc<Mutex<Vec<Player>>>) {
        // Existing player initialization code...
    
        // Initialize existing subsystems
        subsystems::chat::init(socket.clone());
        subsystems::game_logic::init();
        subsystems::leaderboard::init();
        subsystems::level_data::init();
        subsystems::logging::init();
        subsystems::notifications::init();
        subsystems::player_data::init(socket.clone());
    
        // Initialize your custom subsystem
        subsystems::custom_subsystem::init(socket.clone());
    
        define_event!(socket, "test", events::test::main());
    }
  3. Define Your Custom Event

    To define the custom event, add the event definition to the init function of your custom subsystem:

    use crate::define_event;
    
    pub fn init(socket: SocketRef) {
        // Initialize your custom subsystem here
        define_event!(socket, "custom_event", custom_event_handler);
    }

    The define_event! macro will register your custom event with the server.

  4. Handle Your Custom Event

    Implement the logic for handling your custom event in the custom_event_handler function:

    async fn custom_event_handler(socket: SocketRef, data: Value) {
        // Handle your custom event here
        println!("Custom event received: {:?}", data);
    
        // Example: Emitting a response back to the client
        socket.emit("custom_event_response", json!({"status": "success"})).ok();
    }

Example

Here's a complete example of what your custom_subsystem/mod.rs file might look like:

use serde_json::Value;
use socketioxide::extract::SocketRef;
use tracing::info;
use crate::define_event;

pub fn init(socket: SocketRef) {
    // Initialize your custom subsystem here
    define_event!(socket, "custom_event", custom_event_handler);
}

async fn custom_event_handler(socket: SocketRef, data: Value) {
    // Handle your custom event here
    info!("Custom event received: {:?}", data);

    // Example: Emitting a response back to the client
    socket.emit("custom_event_response", json!({"status": "success"})).ok();
}

And in your main.rs file, ensure the on_connect function initializes your custom subsystem:

mod events;
mod macros;
mod structs;
mod subsystems;
mod custom_subsystem;

fn on_connect(socket: SocketRef, Data(data): Data<Value>, players: Arc<Mutex<Vec<Player>>>) {
    let player = Player {
        id: socket.id.to_string(),
        socket: socket.clone(),
        location: None,
    };
    
    players.lock().unwrap().push(player);
    
    info!("Socket.IO connected: {:?} {:?}", socket.ns(), socket.id);
    socket.emit("connected", true).ok();
    socket.emit("auth", data).ok();
    
    subsystems::chat::init(socket.clone());
    subsystems::game_logic::init();
    subsystems::leaderboard::init();
    subsystems::level_data::init();
    subsystems::logging::init();
    subsystems::notifications::init();
    subsystems::player_data::init(socket.clone());
    subsystems::custom_subsystem::init(socket.clone());
    
    define_event!(socket, "test", events::test::main());
}

Testing Your Custom Event

To test your custom event, connect to the server using a Socket.IO client in a basic javascript app and emit the custom_event (Javascript was used for simplicity but any socket-io client library in any language will work):

const socket = io('http://localhost:3000');

socket.emit('custom_event', { message: 'Hello, server!' });

socket.on('custom_event_response', (data) => {
    console.log('Response from server:', data);
});

This will send the custom event to your server, triggering the custom_event_handler function and printing the response in your client console.

⚠️ **GitHub.com Fallback** ⚠️