Releases: NullSablex/rust-samp
v3.0.0
Compared to v2.2.0 (2026/03/15).
Headline: native Open Multiplayer component ABI implemented in pure
Rust (Itanium and MSVC); a single binary now works as a SA-MP
plugin and as a first-class Open Multiplayer component, with no extra
configuration.
Migrating from v2.x (or from the upstream samp-rs fork)
This release contains breaking changes. A plugin written against
v2.x will not compile against v3.0.0 without edits. Minimum diff:
| Before (v2.x / upstream) | After (v3.0.0) |
|---|---|
fn process_tick(&mut self) { … } |
fn on_tick(&mut self, _ctx: TickContext) { … } |
samp::plugin::enable_process_tick() |
samp::plugin::enable_tick() (or enable_tick_with(TickConfig)) |
samp::cell::string::put_in_buffer(buf, s)? |
buf.write_str(s)? / unsized.write_str(size, s)? (put_in_buffer is pub(crate) now) |
samp::raw::functions::Logprintf (variadic) |
Same path, now extern "C" fn(*const i8) — the SDK formats in Rust and passes a single C string |
example-hello/ / example-counter/ / plugin-example/ |
examples/hello/ / examples/counter/ / examples/advanced/ |
Open Multiplayer support comes turned on by default — the build
produces both the SA-MP exports and the ComponentEntryPoint. To
keep the v2.x behavior unchanged, enable the new samp-only feature:
samp = { git = "...", tag = "v3.0.0", features = ["samp-only"] }Two new requirements that affect builds:
- The workspace's
[profile.release]addslto = "thin",
codegen-units = 1,strip = true. Override in your own
Cargo.tomlif you need otherwise. - The i686 target is now strictly required at compile time
(OmpComponenthasconst _layout asserts). Set
target = "i686-unknown-linux-gnu"in.cargo/config.tomlif you
were relying on the host target picking up automatically.
The full step-by-step walkthrough lives in
docs/migration.md — including the new
TickConfig knobs (sa_mp_only(), omp_only(Duration), custom
omp_interval) and how to choose between them.
Crate versions
samp: 2.2.0 → 3.0.0samp-sdk: 2.2.0 → 3.0.0samp-codegen: 1.2.0 → 1.3.0
Breaking changes
SampPlugin::process_tickreplaced by
SampPlugin::on_tick(&mut self, ctx: TickContext)— unified
callback that fires on both servers. Cadence is the server's main
loop on SA-MP and the SDK-ownedITimersComponenttimer on native
Open Multiplayer (interval configurable).TickContext::source
reports the origin (TickSource::SaMp/
TickSource::OmpTimer);TickContext::elapsedis the
wall-clock interval since the previous dispatch.samp::plugin::enable_process_tickreplaced by
samp::plugin::enable_tick()(default config) and
samp::plugin::enable_tick_with(config: TickConfig)(explicit
per-server toggle + Open Multiplayer interval).samp::cell::string::put_in_bufferis nowpub(crate)(was
pub). The public API for writing strings isBuffer::write_str
andUnsizedBuffer::write_str.samp_sdk::raw::functions::Logprintfsignature changed from
variadicextern "C" fn(*const i8, ...)to fixed-arity
extern "C" fn(*const i8)— the SDK formats the message in Rust
and passes a single C string, matching whatlogprintf("%s", msg)
does at the ABI level.- Example crates renamed:
example-hello/→examples/hello/,
example-counter/→examples/counter/,
plugin-example/→examples/advanced/. Workspace members
updated accordingly.
Added — native Open Multiplayer support
samp_sdk::omp— new top-level module with eight submodules:component—OmpComponent,IComponentVTable,
IUIDProviderVTable, opaque types (ICore,IComponentList,
ILogger,IEarlyConfig), default vtable implementations for
both ABIs.component_api—OmpComponentHandletrait, generic
component_name<T>()/component_version<T>()helpers.core—LogLevel,core_print_ln,core_log_ln,
core_print_ln_u8,core_log_ln_u8.events—PawnEventHandler,PawnEventHandlerVTable.server—PAWN_COMPONENT_UID,NUM_AMX_FUNCS,
PawnComponent,ServerComponentList,ServerComponent,
ServerPawnComponent,IEventDispatcherPawn,IPawnScript,
AmxFunctionTable, plus the free functions
query_component,add_pawn_event_handler,
remove_pawn_event_handler,get_pawn_event_dispatcher,
get_amx_from_script,get_amx_functions.timers—TIMERS_COMPONENT_UID,TimersComponent,
ITimersComponent,ITimer,TimerHandlerVTable,
TimerTimeOutHandler,create_repeating_timer,kill_timer,
query_timers_component.types—UID,SemanticVersion(withnewand
with_prerel),StringView(withas_str,try_as_str,
from_static),Colour(withrgb,rgba,from_rgba_u32,
to_rgba_u32and theWHITE,BLACK,NONEconstants),
Vector2,Vector3,Vector4,ComponentType.vtable—subobject_ptr,vtable_slot,
secondary_call_targethelpers for safe access to secondary
vtables.
samp::ompre-exports the module above.samp::pluginnew functions:enable_tick,
enable_tick_with,omp_core,omp_query_component,
omp_query::<T>(typed wrapper forOmpComponentHandle
implementors).samp::pluginnew types:TickConfig,TickContext,
TickSource.SampPluginnew hooks:on_tick(ctx),
on_omp_ready(gated bynot(feature = "samp-only")),
on_component_free(same gating).samp::logre-export —#[native]-expanded code now uses
samp::log::error!, so user crates no longer need to declare
logas a direct dependency just to satisfy the macro.
Added — initialize_plugin! extensions
- Optional metadata fields:
uid: <u64 expression>,
component_name: "...",component_version: (x, y, z). samp-codegenreads[package.metadata.samp]from the project's
Cargo.toml. Resolution order per field:
macro argument >[package.metadata.samp]> derived value
(CARGO_PKG_NAME, parsedCARGO_PKG_VERSION, FNV-1a 64 of
CARGO_PKG_NAME@CARGO_PKG_VERSIONfor the UID).- When the UID is missing from both sources, the generated value is
persisted back intoCargo.tomlunder[package.metadata.samp]
so subsequent builds reuse the same identifier. - Generates the SA-MP exports (
Load,Unload,Supports,
AmxLoad,AmxUnload,ProcessTick) and the Open Multiplayer
ComponentEntryPointby default. Opt out with thesamp-only
feature.
Added — #[native] extensions
- Accepts associated functions (no
self), in addition to
methods. - Return type detection:
Result/AmxResultis matched against
Ok/Err; any other type implementingAmxCellis used as the
return cell directly (no spuriousOk(...)wrapping). - Accepts
&AmxString(and any other&T) parameters — the macro
materializes the owned value fromargs.next_arg()and injects
&localat the call site. - Validates the
name = "..."literal at proc-macro time:
interior\0bytes now produce a compile error instead of
panicking atCString::newduring server load. - Wraps every invocation in
std::panic::catch_unwind. Panics that
would otherwise cross theextern "C"boundary (process abort on
Rust 1.71+) are caught, logged as
[<NativeName>] panic in native: <payload>, and converted to a
0return. - Argument parsing failures now log
[<NativeName>] failed to parse argument #<i> '<name>' (expected type: <Type>)
— both the positional index and the expected type are included.
Added — features and build infrastructure
- New
samp-onlyfeature on bothsampandsamp-sdk: removes
every Open Multiplayer code path. The plugin still loads on Open
Multiplayer, but in legacy mode (no component API). - New workspace
[profile.release]:lto = "thin",
codegen-units = 1,strip = true. Cargo.lockis now committed (removed from.gitignore).Cargo.tomlper crate exposes
package.metadata.docs.rs.default-target = "i686-pc-windows-msvc"features = ["encoding"]so docs.rs builds with the right
target.
- New build scripts:
scripts/build-linux.sh— produces.so
(i686-unknown-linux-gnu) and.dll
(i686-pc-windows-msvcviacargo-xwin --xwin-arch x86, or
i686-pc-windows-gnuwith--samp-only).scripts/build-windows.sh— produces.dllnatively and.so
through WSL or Docker/cross (autodetected; forceable with
--wsl/--docker).
- New helper scripts used by the benchmark workflow:
scripts/append-bench-history.py,scripts/extract-bench.py,
scripts/render-bench-entry.py. - New GitHub workflows:
docs.yml(publishes the MkDocs site),
release.yml(creates releases onv*tags, attaches a source
tarball with only the essential crates),release-drafter.yml,
labels.yml,bench-release.yml(per-release benchmark history
on thebench-databranch). .github/labels.ymland.github/release-drafter.ymlfor the
workflows above.rust.ymlworkflow: action versions bumped to
actions/checkout@v6,actions/upload-artifact@v7,
actions/cache/restore@v5,actions/cache/save@v5(Node 24
baseline); benchmark job restricted to-p samp-sdkto avoid
Unrecognized option: 'save-baseline'; artefact retention now
capped at 14 days.
Added — tests and benchmarks
- Unit tests grew from 80 (v2.2.0) to 207 (this release) — +127
tests. - New per-module test files:
samp-sdk/src/tests/amx_cell.rs(10 tests).samp-sdk/src/tests/amx_string.rs(8 tests).samp-sdk/src/tests/buffer.rs(12 tes...
v2.2.0
Aviso:
A versão 2.1.0 não havia sido declarada anteriormente, então como uma compensação e correção estou trazendo a v2.2.0 com novas adições e melhorias de código. Desde já peço desculpas.
What's Changed
- Update by @NullSablex in #4
Full Changelog: v2.1.0...v2.2.0
v2.1.0
What's Changed
- Fix files optmize by @NullSablex in #1
- Update-cargo by @NullSablex in #2
- Release v2.1.0: segurança, testes, CI e documentação by @NullSablex in #3
New Contributors
- @NullSablex made their first contribution in #1
Full Changelog: https://github.com/NullSablex/rust-samp/commits/v2.1.0
v1.0.1
What's Changed
- Fix files optmize by @NullSablex in #1
Full Changelog: https://github.com/NullSablex/rust-samp/commits/v1.0.1
v1.0.0
Full Changelog: https://github.com/NullSablex/rust-samp/commits/v1.0.0