Skip to content

Add native MP.SetTimeout and MP.CreateThread for async execution #450

@Kipstz

Description

@Kipstz

Summary

Currently, executing code asynchronously or with a delay requires complex workarounds using MP.CreateEventTimer and MP.RegisterEvent. This proposal adds simple, intuitive functions for async execution:

  1. MP.SetTimeout(ms, func) - Execute a function after a delay
  2. MP.CreateThread(func) - Execute a function asynchronously

Current Workaround (Complex)

To achieve async execution today, developers must:

-- Current: 15+ lines of boilerplate for a simple delayed execution
local threadId = 0

function createAsyncTask(func)
    threadId = threadId + 1
    local id = "__thread_" .. threadId
    local handlerName = "__thread_handler_" .. threadId

    _G[handlerName] = function()
        func()
        MP.CancelEventTimer(id)
        _G[handlerName] = nil
    end

    MP.RegisterEvent(id, handlerName)
    MP.CreateEventTimer(id, 100)
end

-- Just to do this:
createAsyncTask(function()
    Wait(5000)
    print("5 seconds later")
end)

Proposed Solution (Simple)

-- SetTimeout: Execute after delay (like JavaScript)
MP.SetTimeout(5000, function()
    print("5 seconds later")
end)

-- CreateThread: Async execution
MP.CreateThread(function()
    print("This runs asynchronously")
    Wait(1000)
    print("Non-blocking code")
end)

Real-World Use Cases

Auto-restart warning system

function scheduleRestart(minutes)
    MP.SetTimeout(minutes * 60000, function()
        shutdownServer()
    end)

    -- Warning messages
    MP.SetTimeout((minutes - 5) * 60000, function()
        MP.SendChatMessage(-1, "^6[SERVER]^r Restart in 5 minutes!")
    end)

    MP.SetTimeout((minutes - 1) * 60000, function()
        MP.SendChatMessage(-1, "^4[SERVER]^r Restart in 1 minute!")
    end)
end

Delayed kick after warning

MP.RegisterEvent("onCheatDetected", function(playerID)
    MP.SendChatMessage(playerID, "^4[AntiCheat]^r Suspicious activity detected. You will be kicked in 10 seconds.")

    MP.SetTimeout(10000, function()
        MP.DropPlayer(playerID, "Kicked by AntiCheat")
    end)
end)

Non-blocking database operations

MP.RegisterEvent("onPlayerJoin", function(playerID)
    -- Don't block the main thread while loading data
    MP.CreateThread(function()
        local data = loadPlayerDataFromDB(playerID)
        applyPlayerData(playerID, data)
        print("Player data loaded for " .. playerID)
    end)
end)

Welcome sequence with delays

MP.RegisterEvent("onPlayerJoin", function(playerID, playerName)
    MP.SendChatMessage(playerID, "^2Welcome " .. playerName .. "!^r")

    MP.SetTimeout(3000, function()
        MP.SendChatMessage(playerID, "^3Type /help for available commands^r")
    end)

    MP.SetTimeout(6000, function()
        MP.SendChatMessage(playerID, "^3Join our Discord: discord.gg/example^r")
    end)
end)

Benefits

Current Approach Proposed Approach
15+ lines of boilerplate 1 function call
Manual cleanup required Automatic cleanup
Error-prone Simple and reliable
Hard to read Intuitive syntax
Must manage event timers manually Native implementation

Technical Notes

  • Backward compatible: Does not affect existing MP.CreateEventTimer functionality
  • Familiar pattern: Same syntax as JavaScript setTimeout - millions of developers already know it
  • Performance: Native C++ implementation would be faster than Lua workarounds
  • Memory safe: Automatic cleanup of handlers after execution

Additional Context

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


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

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidThis doesn't seem right

    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