Introduction¶
rust-samp is a Rust toolkit for building server plugins for SA-MP (San Andreas Multiplayer) and native components for Open Multiplayer. The same compiled binary works on both servers: SA-MP loads it through the legacy plugin ABI, and Open Multiplayer loads it as a first-class component without any extra configuration.
Fork of samp-rs by ZOTTCE. Modernized for Rust edition 2024 and extended with a pure-Rust implementation of the Open Multiplayer component ABI (Itanium and MSVC), without
bindgenor any C/C++ dependency.
Why Rust¶
Traditional plugins are written in C/C++, where memory errors (buffer overflow, use-after-free, dangling pointers) are the leading cause of server crashes. Rust eliminates those bugs at compile time while keeping performance on par with C.
rust-samp adds, on top of that foundation:
- Native derivation via the
#[native]attribute — no manual FFI boilerplate. - Automatic argument parsing from AMX cells into Rust types.
- Panic-safe wrappers — panics inside a native are caught and logged instead of aborting the server process.
AmxStringwithDeref<Target = str>— every&strmethod is available without.to_string(); the decoded string is computed once and cached.- Typed Pawn arrays —
Buffer::get_as::<f32>/set_as::<bool>/iter_as::<T>coverFloat:andbool:arrays without manual bit manipulation. - Optional
encodingfeature — Windows-1251 / Windows-1252 string conversion viaencoding_rs. - Turnkey logger —
samp::enable_logger!()installs a complete pipeline (per-plugin file, size-based rotation intologs/archive/, banner, runtime-adjustable level) in a single call. Customizable viaLoggerConfigor DIY throughsamp::plugin::logger()for advanced cases. Routes to the server's own log sink (logprintfon SA-MP,ICore::logLnU8on native Open Multiplayer) alongside the file. - Native Open Multiplayer support — pure-Rust implementation of the component ABI (Itanium and MSVC) so a single binary works as a SA-MP plugin and as an Open Multiplayer component.
Workspace structure¶
| Crate | Version | Description |
|---|---|---|
samp |
3.1.0 | Main crate — depend on this one. Re-exports the SDK and the proc macros. |
samp-sdk |
3.0.0 | Low-level bindings: AMX VM + Open Multiplayer component ABI. |
samp-codegen |
1.3.0 | Procedural macros (#[native], initialize_plugin!, SampPlugin). |
In practice, only the samp crate is referenced by a plugin's
Cargo.toml. It re-exports everything from samp-sdk and samp-codegen.
A first taste¶
use samp::prelude::*;
use samp::{native, initialize_plugin, SampPlugin};
#[derive(SampPlugin, Default)]
struct Plugin;
impl Plugin {
#[native(name = "TestNative")]
fn my_native(&mut self, _amx: &Amx, text: &AmxString) -> AmxResult<bool> {
println!("rust plugin: {}", &**text);
Ok(true)
}
}
initialize_plugin!(
type: Plugin,
natives: [Plugin::my_native],
);
The next chapters set up the toolchain and walk through a plugin from scratch.