Skip to main content

Module component

Module component 

Source
Expand description

IComponent interface from the Open Multiplayer SDK in pure Rust.

The memory layout and vtable indices were derived from the public specification of the Open Multiplayer SDK (https://github.com/openmultiplayer/open.mp-sdk). No SDK code was copied — only signatures and vtable layouts were used as reference for this pure Rust reimplementation.

§Platform support

TargetSA-MPnative Open Multiplayer
i686-unknown-linux-gnuyesyes (Itanium ABI)
i686-pc-windows-msvcyesyes (MSVC ABI)
i686-pc-windows-gnuyesno (incompatible ABI)

§Multiple inheritance and vtables

IComponent : public IExtensible, public IUIDProvider results in two vtable pointers in the object. The offsets differ between Itanium (Linux GCC) and MSVC because the FlatHashMap (robin_hood::unordered_flat_map) has a different size on the two platforms — confirmed via disasm of omp-server.exe.

Offset  Field (Linux / GCC i686)
------  -----
 0      vtable*      (primary: IExtensible + IComponent)
 4..39  _misc_ext    (robin_hood::unordered_flat_map, 36 bytes)
40      uid_vtable*  (secondary: IUIDProvider)
44      uid          (u64 — plugin's own field)
52      plugin_ptr   (*mut () — plugin's own field)

Offset  Field (Windows / MSVC i686)
------  -----
 0      vtable*      (primary: IExtensible + IComponent)
 4..55  _misc_ext    (52 bytes: padding + robin_hood + trailing padding)
56      uid_vtable*  (secondary: IUIDProvider) — offset hardcoded by the server
60      _uid_pad     (4 bytes to align uid (u64) to 8 bytes)
64      uid          (u64 — plugin's own field)
72      plugin_ptr   (*mut () — plugin's own field)

§Primary vtable

Itanium ABI — two destructor slots (D1 complete + D0 deleting):

[0]  getExtension
[1]  addExtension
[2]  removeExtension(ext*)
[3]  removeExtension(uid)
[4]  ~destructor D1 (complete object)
[5]  ~destructor D0 (deleting)
[6]  supportedVersion
[7]  componentName
[8]  componentType
[9]  componentVersion
[10] onLoad
[11] onInit
[12] onReady
[13] onFree
[14] provideConfiguration
[15] free
[16] reset
[17] getUID (the `IUIDProvider` override also lands in the primary vtable)

MSVC ABI — single destructor (scalar deleting) between IExtensible and IComponent:

[0]  getExtension
[1]  addExtension
[2]  removeExtension(uid)   <- MSVC emits an overload set in REVERSE
[3]  removeExtension(ext*)     declaration order
[4]  ~destructor (single scalar deleting — MSVC does not emit D0)
[5]  supportedVersion
[6]  componentName
[7]  componentType
[8]  componentVersion
[9]  onLoad
[10] onInit
[11] onReady
[12] onFree
[13] provideConfiguration
[14] free
[15] reset

The slots were confirmed by runtime + disasm of omp-server.exe (componentVersion calls at [edx+0x20] = slot 8; componentName at [eax+0x18] = slot 6).

§Secondary vtable — IUIDProvider

Itanium ABI — a single slot, exactly like MSVC. IUIDProvider declares no virtual destructor, so its secondary vtable holds only the getUID thunk (confirmed in the official Timers.so and Pawn.so: the secondary vtable at offset-to-top -40 has one entry).

[0]  getUID

MSVC ABI — only getUID (IUIDProvider does not declare a virtual destructor):

[0]  getUID

Structs§

IComponentList
IComponentList* — list of loaded components. Received in on_init; use to query other components.
IComponentVTable
Primary IComponent vtable for the MSVC ABI (Windows).
ICore
ICore* — opaque pointer to the Open Multiplayer server core. Received in on_load; use only for caching or future queries.
IEarlyConfig
IEarlyConfig* — configuration during initialization.
ILogger
ILogger* — server logging interface.
IUIDProviderVTable
Secondary IUIDProvider vtable for the MSVC ABI (Windows).
OmpComponent
Rust object with a layout compatible with Open Multiplayer’s IComponent*.

Functions§

comp_component_type⚠
Safety
comp_on_free⚠
Safety
comp_on_init⚠
Safety
comp_on_ready⚠
Safety
comp_provide_configuration⚠
Safety
comp_supported_version⚠
Safety
ext_add_extension⚠
Safety
ext_destructor⚠
Scalar deleting destructor — no-op: cleanup is done via free(). No explicit parameter: this in ECX, no args on the stack (avoids ret 4).
ext_get_extension⚠
Safety
ext_remove_extension_ptr⚠
Safety
ext_remove_extension_uid⚠
Safety
uid_get_uid⚠
getUID() via the secondary IUIDProvider vtable (MSVC ABI).