Skip to content

Support anonymous functions and multiple handlers in MP.RegisterEvent #449

@Kipstz

Description

@Kipstz

Summary

Currently, MP.RegisterEvent only accepts a function name as a string, which limits flexibility for plugin developers. This proposal adds support for:

  1. Anonymous functions - Pass functions directly instead of referencing by name
  2. Multiple handlers - Register multiple handlers for the same event

Current Behavior

-- Must define named function first
function onPlayerJoin(pid)
    print("Player joined: " .. pid)
end
MP.RegisterEvent("onPlayerJoin", "onPlayerJoin")

-- ❌ Cannot do this:
MP.RegisterEvent("onPlayerJoin", function(pid)
    print("Player joined")
end)

-- ❌ Cannot register multiple handlers for same event

Examples

Backward Compatibility (existing syntax still works)

function handleServerCommand(cmd, args)
    print("Executing command: " .. cmd)
end
MP.RegisterEvent("onConsoleInput", "handleServerCommand")

New Anonymous Function Syntax

MP.RegisterEvent("onChatMessage", function(playerID, playerName, message)
    if message:match("^/help") then
        MP.SendChatMessage(playerID, "Available commands: /help, /info")
    end
end)

Multiple Plugins, Same Event

-- Plugin: AntiCheat
MP.RegisterEvent("onPlayerJoin", function(playerID)
    checkPlayerBan(playerID)
end)

-- Plugin: WelcomeSystem
MP.RegisterEvent("onPlayerJoin", function(playerID)
    sendWelcomeMessage(playerID)
end)

-- Plugin: Analytics
MP.RegisterEvent("onPlayerJoin", function(playerID)
    logPlayerJoin(playerID)
end)

✅ All three handlers execute when a player joins!

Technical Approach

  1. Modify MP.RegisterEvent to accept sol::object (string OR function)
  2. If a function is passed, store it in _G with a generated unique name (e.g., __AnonymousHandler_onPlayerJoin_1)
  3. Use an atomic counter per state to ensure unique naming
  4. Register the generated name with the existing event system

Benefits

  • Cleaner code: No need to define and name every handler function
  • Modularity: Multiple plugins can hook into the same event independently
  • Familiar pattern: Similar to how events work in Node.js, FiveM/CFX, and other frameworks
  • Backward compatible: Existing string-based registrations continue to work

Additional Context

I've implemented this as a Lua wrapper in my plugin (https://github.com/Kipstz/Tree-BeamMP-Plugin/blob/main/_tree/events.lua), but a native C++ implementation would be more performant and benefit all plugin developers.

I'm willing to implement this feature and submit a PR if the approach is approved.

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExternal contribution(s) appreciated

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions