Skip to content

LeviLamina mods in the language you like

Rust, Go, Zig or C++. Install Pier, write a dynamic library, drop it into plugins/, and the server loads it; mods of different languages call each other.

Get started API Your first mod

src/lib.rs
use levilamina::prelude::*;
use levilamina::event::{self, names};

struct Hello {
    join: Option<Listener>,
}

impl LeviMod for Hello {
    fn on_load(_ctx: &ModContext) -> Result<Self> {
        Ok(Hello { join: None })
    }

    fn on_enable(&mut self, _ctx: &ModContext) -> Result<()> {
        self.join = Some(event::subscribe(names::PLAYER_JOIN, |ev| {
            if let Ok(name) = ev.str_at("_player.name") {
                Logger::get().info(&format!("{name} joined"));
            }
        })?);
        Ok(())
    }
}

levilamina::register_mod!(Hello);
  • The language you know


    Rust, C++, Go and Zig have official bindings. A language not on the list can plug in too, as long as it can call a C function.

    What is Pier

  • Mods talk to each other


    When a Go mod calls a service a Rust mod provides, Pier hands the request over and the reply back; neither side needs to know the other's language.

    Talking to other mods

  • An unreadable value is an error


    When the host cannot read a value, the call returns an error naming what it tried to read, and your code can refuse the action.

    API overview

  • Upgrades without rebuilding


    While the ABI version stays the same, a mod built against an older Pier loads unchanged; a real incompatibility is refused at load with the reason.

    Compatibility

  • A watchdog for hangs


    When a mod holds a server thread too long, the watchdog logs which mod and where, then ends the process so a supervisor brings the server back.

    The watchdog

  • Right at home in LeviLamina


    LeviLamina's events, commands, players and world are yours to use, and native plugins call your services through the bridge.

    The bridge