| Crates.io | horizon-plugin-api |
| lib.rs | horizon-plugin-api |
| version | 0.2.2 |
| created_at | 2024-11-07 03:58:26.582799+00 |
| updated_at | 2025-06-13 06:26:17.49922+00 |
| description | API utils and shared types for Horizon plugins |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1439461 |
| size | 40,592 |
I'll explain how to implement and use the Horizon Plugin API in a project. The plugin API you've shared is a framework for building modular functionality for the Horizon game server.
The Horizon Plugin API provides a way to extend the Horizon game server with custom functionality through plugins. Here's how it works:
Let's create a simple plugin that adds chat functionality to the Horizon server.
First, create a new directory in the plugins folder:
mkdir -p plugins/chat_plugin/src
cd plugins/chat_plugin
[package]
name = "chat_plugin"
version = "0.1.0"
edition = "2021"
[dependencies]
horizon-plugin-api = "0.2.0"
horizon_data_types = "0.4.0"
socketioxide = "0.15.1"
parking_lot = "0.12.3"
serde = "1.0.216"
serde_json = "1.0.134"
Create src/lib.rs with the following code:
use horizon_data_types::Player;
use socketioxide::extract::SocketRef;
pub use horizon_plugin_api::{Plugin, Pluginstate, LoadedPlugin};
use parking_lot::RwLock;
use std::sync::Arc;
use std::collections::HashMap;
use serde_json::{json, Value};
// Define the plugin API trait
pub trait PluginAPI {
fn player_joined(&self, socket: SocketRef, player: Arc<RwLock<horizon_data_types::Player>>);
}
// Define the plugin constructor trait
pub trait PluginConstruct {
fn new(plugins: HashMap<String, (Pluginstate, Plugin)>) -> Plugin;
fn get_structs(&self) -> Vec<&str>;
}
// Implement the constructor for the Plugin type
impl PluginConstruct for Plugin {
fn new(_plugins: HashMap<String, (Pluginstate, Plugin)>) -> Plugin {
println!("Chat plugin initialized!");
Plugin {}
}
fn get_structs(&self) -> Vec<&str> {
vec!["ChatMessage"]
}
}
// Implement the API for the Plugin type
impl PluginAPI for Plugin {
fn player_joined(&self, socket: SocketRef, player: Arc<RwLock<horizon_data_types::Player>>) {
println!("Player joined chat system");
setup_chat_listeners(socket, player);
}
}
// Setup chat event listeners
fn setup_chat_listeners(socket: SocketRef, player: Arc<RwLock<Player>>) {
// Handle incoming chat messages
socket.on("chat_message", move |data: socketioxide::extract::Data<Value>, socket: SocketRef| {
let message = data.0;
// Get player name
let player_name = player.read().get_name().unwrap_or("Unknown".to_string());
// Create the message payload with sender info
let payload = json!({
"sender": player_name,
"message": message["text"],
"timestamp": chrono::Utc::now().timestamp()
});
// Broadcast the message to all clients
socket.broadcast().emit("chat_broadcast", payload).ok();
// Echo back to sender with confirmation
socket.emit("chat_sent", json!({"success": true})).ok();
println!("Chat message processed from {}", player_name);
});
}
The plugin system automatically loads plugins from the plugins directory. Here's how the server interacts with the plugins:
PluginManager scans the plugins directory during startupnew() methodplayer_joined when appropriateTo test our chat plugin:
cd plugins/chat_plugin
cargo build
cd ../..
cargo run
Plugins can interact with each other through dependencies. For example, our chat plugin could depend on a permission plugin to check if users are allowed to send messages.
// In chat_plugin/src/lib.rs:
impl PluginConstruct for Plugin {
fn new(plugins: HashMap<String, (Pluginstate, Plugin)>) -> Plugin {
// Get reference to permission plugin
if let Some((_, permission_plugin)) = plugins.get("permission_plugin") {
// Cast to the permission plugin's API type
let permission_api = permission_plugin as &dyn permission_plugin::PluginAPI;
// Use the permission plugin's functionality
println!("Permission plugin is available: {}",
permission_api.get_version());
}
Plugin {}
}
// Rest of implementation...
}
A complete Horizon project with plugins would look like:
horizon-project/
├── backend_api/ # Backend API implementation
├── plugin_api/ # Plugin API implementation
├── plugins/
│ ├── chat_plugin/ # Our chat plugin
│ ├── permission_plugin/
│ └── other_plugins/
├── server/ # Main server implementation
└── Cargo.toml # Workspace configuration
The plugin system provides a clean, modular architecture that makes it easy to extend the Horizon server with new functionality without modifying the core server code.