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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions