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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions