Skip to content

Releases: NullSablex/rust-samp

v3.1.0

09 Jun 17:25
cb45673

Choose a tag to compare

Headline: turnkey logger — samp::enable_logger!() installs a complete
per-plugin logging pipeline (file under logs/, size-based rotation
into logs/archive/, prefix derived from CARGO_PKG_NAME, startup
banner, runtime-adjustable level) in a single call. The previous
samp::plugin::logger() DIY path stays unchanged for advanced cases.

v3.1.0 is also the first version available on crates.io
rust-samp,
rust-samp-sdk and
rust-samp-codegen.
Earlier releases (v3.0.0 and the entire v2.x line) are not published to
the registry; plugins targeting those versions must keep using a git
dependency. The library names (samp, samp_sdk, samp_codegen)
are unchanged; only the package names differ on the registry to
avoid colliding with the upstream samp-rs fork.

Crate versions

  • rust-samp (lib samp): 3.0.0 → 3.1.0
  • rust-samp-sdk (lib samp_sdk): 3.0.0 — unchanged (metadata only)
  • rust-samp-codegen (lib samp_codegen): 1.3.0 — unchanged (metadata only)

Installation

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

[dependencies]
samp = { package = "rust-samp", version = "3" }
log  = "0.4"

The package is published as rust-samp; the alias keeps the
source-level use samp::prelude::*; imports unchanged. Git consumers
do not need to update anything — both names continue to resolve to the
same library.

New features

  • Turnkey logger — new module samp::logger plus the
    samp::enable_logger!() and samp::enable_logger_with!(cfg) macros.
    The macros capture the caller's CARGO_PKG_* at compile time and
    install a log::Log implementation that routes through both the
    server's log sink and a per-plugin file.
  • LoggerConfig builder — every aspect of the pipeline is
    configurable through fluent setters: directory, filename,
    prefix, level, also_to_server, banner, file_format,
    server_format, rotation_size_mb, rotation_keep,
    rotation_no_cleanup, no_rotation, no_banner, banner_with.
  • Format templatesfile_format and server_format accept
    {timestamp}, {level}, {message} and (server-only) {prefix}
    placeholders with optional alignment specifiers ({level:>5},
    {level:<5}, {level:^5}). Unknown placeholders pass through
    verbatim so typos are visible.
  • Banner modesBannerMode::Default (5-line banner from
    CARGO_PKG_*), BannerMode::Off, and BannerMode::Custom (closure
    receiving BannerMetadata and returning the lines to render).
  • Size-based rotation — when the active file passes
    rotation_size_mb (default 50 MB), it is renamed into
    {directory}/archive/{filename}.{N} and a fresh active file is
    opened. Two strategies are available:
    • Append-style (default): every rotation uses the next free
      index, archives are never deleted by the SDK, the dev keeps
      full control over cleanup. The archive folder is created lazily on
      the first rotation; the next index survives restarts (rescanned at
      install time).
    • Shift-style — opt-in via rotation_keep(N): .log.N is
      deleted, every other archive shifts down, active becomes .log.1.
      Disk footprint becomes (keep + 1) * rotation_size_mb.
  • Runtime level adjustmentsamp::logger::set_level(...) and
    samp::logger::level() let plugins expose a Pawn-side knob for log
    verbosity (e.g. a MyPlugin_SetLogLevel(level) native).
  • InstallErrorDisplay + Error with source() exposing
    the inner std::io::Error for the Io variant.

Migrating to the turnkey logger

The previous handcrafted fern::Dispatch pattern keeps working —
adoption is optional.

Before (v3.0.0) After (v3.1.0)
fern::Dispatch::new().level(...).chain(samp::plugin::logger()).chain(fern::log_file(...)?).format(...).apply()?; samp::enable_logger!() inside on_load
Hand-built prefix string format_args!("[my-plugin][{}]: {}", record.level(), message) Automatic [CARGO_PKG_NAME] prefix
Manually managing the log filename Default logs/{CARGO_PKG_NAME}.log
External logrotate setup for file growth Built-in 50 MB rotation into logs/archive/
Pawn-side SetLogLevel(level) native backed by a static AtomicI32 samp::logger::set_level(LevelFilter) direct

See docs/logging.md for the full reference,
including the three layers (turnkey / LoggerConfig / DIY with fern),
format placeholders, rotation modes, and runtime tuning.

Packaging (crates.io)

The three workspace crates now have crates.io-ready metadata
(description, keywords, categories, rust-version, per-crate
README.md) and centralized shared fields in [workspace.package].

  • Package names: rust-samp, rust-samp-sdk, rust-samp-codegen.
    The upstream samp / samp-sdk / samp-codegen names on crates.io
    belong to the original samp-rs author and are not the publication
    target of this fork.

  • Library names: unchanged — samp, samp_sdk, samp_codegen.
    Existing use samp::prelude::*; keeps compiling.

  • Crates.io consumers add the package alias to their
    Cargo.toml:

    [dependencies]
    samp = { package = "rust-samp", version = "3" }
  • Git consumers (samp = { git = "..." }) need no change — the
    workspace exposes both names.

Build

  • MSRV bumped to Rust 1.88 (was 1.85). Required by stable
    i32::cast_unsigned / u32::cast_signed (used internally for AMX
    cell bit conversions) and by the patched time 0.3.47 / time-core 0.1.8 / time-macros 0.2.27. Declared via
    [workspace.package].rust-version = "1.88".
  • New transitive dependencytime = "0.3.47" (features
    local-offset, formatting, macros) is pulled in by the turnkey
    logger for timestamp formatting. The chrono crate is not added.
    The minimum is pinned to 0.3.47 to pick up the fix for
    RUSTSEC-2026-0009
    (DoS via stack exhaustion, medium severity).

CI / release infrastructure

  • Release notes are now auto-assembled — workflow .github/workflows/release.yml
    combines the curated CHANGELOG section with the GitHub-native
    releases/generate-notes API output, keeping the "New Contributors"
    block and the "Full Changelog" comparison link while dropping the
    redundant ## What's Changed header.
  • Crates.io publication is wired into the release workflow — on
    v* tag push (and manual workflow_dispatch with a dry_run
    input), the workflow validates the workspace, then publishes
    rust-samp-sdkrust-samp-codegenrust-samp in dependency
    order with a 30 s sleep between steps. Each cargo publish step
    gracefully skips when the version is already on crates.io, so a
    patch release that bumps only one crate goes through unattended.
  • Bench jobs were updated to reference rust-samp-sdk instead of
    the pre-rename samp-sdk package id.
  • Release-drafter template no longer emits the duplicated
    ## What's Changed heading at the top of release notes.

Documentation

  • docs/logging.md — rewritten end-to-end (139 → 413 lines).
    Covers the three layers, format placeholders and alignment specs,
    banner modes, rotation strategies, runtime level adjustment, and a
    pitfalls section.
  • docs/api-reference.md — new samp::logger section with the
    full builder signature, error type, and placeholder reference.
  • docs/migration.md — new v3.0.0 → v3.1.0 section with the
    before/after migration table and crates.io adoption notes.
  • docs/first-plugin.md — new "Enabling logging" section showing
    the one-liner inside on_load.
  • docs/plugin-anatomy.md — explicit note that enable_logger!
    belongs in on_load, not the constructor block (server's log sink
    is not connected yet during construction).
  • docs/index.md — the integrated-logging bullet now describes
    the turnkey path; workspace table reflects the new samp version.
  • docs/advanced-examples.md — the examples/counter snippet
    matches the source change (uses samp::enable_logger!() instead of
    the handcrafted fern::Dispatch).
  • Dual-availability sweepREADME.md, migration.md,
    docs/setup.md, docs/encoding.md and docs/migration.md now show
    both installation paths side-by-side (crates.io for v3.1.0+, git for
    any version including v3.0.0 and earlier) with a consistent
    package = "rust-samp" snippet. The workspace version table in
    README.md was bumped to reflect the new samp 3.1.0.

Examples

  • examples/counter (1.0.0 → 1.1.0)on_load now calls
    samp::enable_logger!(); the fern dependency was dropped.
  • examples/hello (1.0.0 → 1.0.1), examples/advanced (1.1.0 →
    1.1.1)
    — switched to the package = "rust-samp" alias so the path
    dependency matches the published name. No source changes.

Repository housekeeping

  • ROADMAP.md moved out of version control (now under .gitignore)
    — it stays as a local working document for the maintainer and is no
    longer shipped to crates.io tarballs or GitHub.
  • .github/CODEOWNERS added.
  • CNAME removed (project pages are served from the default
    nullsablex.github.io/rust-samp/ URL).

Code quality

  • Clippy -D warnings and `-W clippy::pedanti...
Read more

v3.0.0

09 Jun 00:30
a08348d

Choose a tag to compare

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] adds lto = "thin",
    codegen-units = 1, strip = true. Override in your own
    Cargo.toml if you need otherwise.
  • The i686 target is now strictly required at compile time
    (OmpComponent has const _ layout asserts). Set
    target = "i686-unknown-linux-gnu" in .cargo/config.toml if 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.0
  • samp-sdk: 2.2.0 → 3.0.0
  • samp-codegen: 1.2.0 → 1.3.0

Breaking changes

  • SampPlugin::process_tick replaced 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-owned ITimersComponent timer on native
    Open Multiplayer (interval configurable). TickContext::source
    reports the origin (TickSource::SaMp /
    TickSource::OmpTimer); TickContext::elapsed is the
    wall-clock interval since the previous dispatch.
  • samp::plugin::enable_process_tick replaced 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_buffer is now pub(crate) (was
    pub). The public API for writing strings is Buffer::write_str
    and UnsizedBuffer::write_str.
  • samp_sdk::raw::functions::Logprintf signature changed from
    variadic extern "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 what logprintf("%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:
    • componentOmpComponent, IComponentVTable,
      IUIDProviderVTable, opaque types (ICore, IComponentList,
      ILogger, IEarlyConfig), default vtable implementations for
      both ABIs.
    • component_apiOmpComponentHandle trait, generic
      component_name<T>() / component_version<T>() helpers.
    • coreLogLevel, core_print_ln, core_log_ln,
      core_print_ln_u8, core_log_ln_u8.
    • eventsPawnEventHandler, PawnEventHandlerVTable.
    • serverPAWN_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.
    • timersTIMERS_COMPONENT_UID, TimersComponent,
      ITimersComponent, ITimer, TimerHandlerVTable,
      TimerTimeOutHandler, create_repeating_timer, kill_timer,
      query_timers_component.
    • typesUID, SemanticVersion (with new and
      with_prerel), StringView (with as_str, try_as_str,
      from_static), Colour (with rgb, rgba, from_rgba_u32,
      to_rgba_u32 and the WHITE, BLACK, NONE constants),
      Vector2, Vector3, Vector4, ComponentType.
    • vtablesubobject_ptr, vtable_slot,
      secondary_call_target helpers for safe access to secondary
      vtables.
  • samp::omp re-exports the module above.
  • samp::plugin new functions: enable_tick,
    enable_tick_with, omp_core, omp_query_component,
    omp_query::<T> (typed wrapper for OmpComponentHandle
    implementors).
  • samp::plugin new types: TickConfig, TickContext,
    TickSource.
  • SampPlugin new hooks: on_tick(ctx),
    on_omp_ready (gated by not(feature = "samp-only")),
    on_component_free (same gating).
  • samp::log re-export — #[native]-expanded code now uses
    samp::log::error!, so user crates no longer need to declare
    log as 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-codegen reads [package.metadata.samp] from the project's
    Cargo.toml. Resolution order per field:
    macro argument > [package.metadata.samp] > derived value
    (CARGO_PKG_NAME, parsed CARGO_PKG_VERSION, FNV-1a 64 of
    CARGO_PKG_NAME@CARGO_PKG_VERSION for the UID).
  • When the UID is missing from both sources, the generated value is
    persisted back into Cargo.toml under [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
    ComponentEntryPoint by default. Opt out with the samp-only
    feature.

Added — #[native] extensions

  • Accepts associated functions (no self), in addition to
    methods.
  • Return type detection: Result / AmxResult is matched against
    Ok/Err; any other type implementing AmxCell is used as the
    return cell directly (no spurious Ok(...) wrapping).
  • Accepts &AmxString (and any other &T) parameters — the macro
    materializes the owned value from args.next_arg() and injects
    &local at the call site.
  • Validates the name = "..." literal at proc-macro time:
    interior \0 bytes now produce a compile error instead of
    panicking at CString::new during server load.
  • Wraps every invocation in std::panic::catch_unwind. Panics that
    would otherwise cross the extern "C" boundary (process abort on
    Rust 1.71+) are caught, logged as
    [<NativeName>] panic in native: <payload>, and converted to a
    0 return.
  • 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-only feature on both samp and samp-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.lock is now committed (removed from .gitignore).
  • Cargo.toml per 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-msvc via cargo-xwin --xwin-arch x86, or
      i686-pc-windows-gnu with --samp-only).
    • scripts/build-windows.sh — produces .dll natively 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 on v* tags, attaches a source
    tarball with only the essential crates), release-drafter.yml,
    labels.yml, bench-release.yml (per-release benchmark history
    on the bench-data branch).
  • .github/labels.yml and .github/release-drafter.yml for the
    workflows above.
  • rust.yml workflow: 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-sdk to 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 r...
Read more

v2.2.0

15 Mar 00:36
cf07ec0

Choose a tag to compare

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

Full Changelog: v2.1.0...v2.2.0

v2.1.0

23 Feb 04:10
2f04c37

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: https://github.com/NullSablex/rust-samp/commits/v2.1.0

v1.0.1

19 Feb 01:03
75b8962

Choose a tag to compare

What's Changed

Full Changelog: https://github.com/NullSablex/rust-samp/commits/v1.0.1

v1.0.0

19 Feb 00:55
a50723d

Choose a tag to compare