Plugin Development ru - Pa-dej/Vex GitHub Wiki

Разработка плагинов (Русский)

Этот туториал показывает полный путь создания плагина на vex-proxy-sdk.

Шаг 1: Создать Rust‑проект

cargo new whitelist_plugin --lib
cd whitelist_plugin

Шаг 2: Настроить Cargo.toml как cdylib

[package]
name = "whitelist_plugin"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
vex-proxy-sdk = "3.0"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"

Шаг 3: Реализовать VexPlugin

Шаг 4: Зарегистрировать события

Шаг 5: Сборка

cargo build --release

Библиотека появится в target/release/:

  • Windows: whitelist_plugin.dll
  • Linux: libwhitelist_plugin.so
  • macOS: libwhitelist_plugin.dylib

Шаг 6: Деплой

Скопируйте библиотеку в plugins/ рядом с vex.toml и перезагрузите:

curl -X POST http://127.0.0.1:8080/reload -H "x-admin-token: change-me"

Полный рабочий пример

Плагин делает следующее:

  • Загружает config.yml со списком разрешённых игроков
  • Отменяет OnPreLogin для не‑whitelist игроков
  • Отправляет приветствие при логине
  • Шлёт broadcast каждые 60 секунд
  • Регистрирует команду /whitelist
  • Регистрирует Prometheus‑счётчик

config.yml (в data dir плагина)

allowed:
  - Alice
  - Bob
welcome: "Welcome to the server!"
broadcast: "Remember to be kind to each other!"

src/lib.rs

use std::error::Error;
use std::sync::Arc;
use serde::Deserialize;
use vex_proxy_sdk::VexPlugin;
use vex_proxy_sdk::api::{PluginApi, CommandContext};
use vex_proxy_sdk::event::{OnPreLogin, OnLoginSuccess};
use vex_proxy_sdk::metrics::Counter;

#[derive(Clone, Debug, Deserialize)]
struct WhitelistConfig {
    allowed: Vec<String>,
    welcome: String,
    broadcast: String,
}

const DEFAULT_CONFIG: &str = r#"
allowed:
  - Alice
  - Bob
welcome: "Welcome to the server!"
broadcast: "Remember to be kind to each other!"
"#;

struct WhitelistPlugin;

impl VexPlugin for WhitelistPlugin {
    fn name(&self) -> &'static str { "whitelist_plugin" }
    fn version(&self) -> &'static str { "0.1.0" }

    fn on_load(&self, api: Arc<PluginApi>) -> Result<(), Box<dyn Error + Send + Sync>> {
        api.config.save_default("config.yml", DEFAULT_CONFIG)?;
        let cfg: WhitelistConfig = api.config.load_yaml("config.yml")?;
        let cfg = Arc::new(cfg);

        let denied: Counter = api.metrics.counter(
            "whitelist_denied_total",
            "Denied connections by whitelist plugin"
        )?;

        // Pre-login whitelist check
        let cfg_pre = cfg.clone();
        let denied_pre = denied.clone();
        api.events.on::<OnPreLogin, _, _>(move |event| {
            let cfg_pre = cfg_pre.clone();
            let denied_pre = denied_pre.clone();
            async move {
                if !cfg_pre.allowed.iter().any(|name| name.eq_ignore_ascii_case(&event.username)) {
                    denied_pre.inc();
                    event.deny("You are not whitelisted.");
                }
            }
        });

        // Welcome message after successful login
        let cfg_login = cfg.clone();
        api.events.on::<OnLoginSuccess, _, _>(move |event| {
            let cfg_login = cfg_login.clone();
            async move {
                event.player.send_message(&cfg_login.welcome);
            }
        });

        // Scheduled broadcast every 60s
        let proxy = api.proxy.clone();
        let cfg_broadcast = cfg.clone();
        api.scheduler.run_timer(60_000, move || {
            let proxy = proxy.clone();
            let msg = cfg_broadcast.broadcast.clone();
            async move {
                proxy.broadcast(&msg);
            }
        });

        // /whitelist command
        let cfg_cmd = cfg.clone();
        api.commands.register(
            "whitelist",
            "vex.whitelist",
            move |ctx: CommandContext| {
                let cfg_cmd = cfg_cmd.clone();
                async move {
                    let list = cfg_cmd.allowed.join(\", \");
                    ctx.reply(&format!(\"Whitelisted: {}\", list));
                }
            }
        );

        api.logger.info(\"whitelist_plugin loaded\");
        Ok(())
    }

    fn on_unload(&self) {}
}

#[no_mangle]
pub extern \"C\" fn vex_plugin_create() -> Box<dyn VexPlugin> {
    Box::new(WhitelistPlugin)
}

See also

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