Lua:IPC

From WolfWiki
Jump to: navigation, search

Lua: IPC - Communication between Scripts

If you have several scripts, which access the same data, you can have one script, which manages this data and one or more scripts reading (or writing) this data.

For communication between these scripts, use the et.IPCSend() and et_IPCReceive( ) functions. You cannot receive some data and send it back in the same (server) frame. These example scripts illustrate how to pass requests and the answers back and forth.

The ipcdemo-admin.lua script must be loaded first (i.e. earlier in the lua_modules cvar) otherwise the ipcdemo-cmd.lua cannot find it.

ipcdemo-admin.lua

-- ipcdemo-admin.lua
local IPCQueue = {}
local AdminGUIDs = {
        -- name,       guid,                              level
        { "Vetinari", "ABCDEF1234567890ABCDEF1234567890", 5 },
        { "Havelock", "1234567890ABCDEF1234567890ABCDEF", 3 }
    }
 
function et_InitGame(levelTime, randomSeed, restart)
     et.RegisterModname("ipcdemo-admin.lua")
end
 
function et_IPCReceive(vm, msg)
    local level
    local junk1, junk2, id = string.find(msg, "IsAdmin:%s+(%d+)")
    if id ~= nil then
        id    = tonumber(id)
        guid  = et.Info_ValueForKey(et.trap_GetUserinfo(id), "cl_guid")
        level = table.foreach(AdminGUIDs,
            function(i, admin)
                if admin[2] == guid then
                    return(admin[3])
                end
            end
        )
        if level == nil then
            level = 0
        end
        table.insert(IPCQueue, { vm, level, id })
    end
end
 
function et_RunFrame(lvltime)
    table.foreach(IPCQueue,
        function(i, queue)
            local ok = et.IPCSend(queue[1],
                            string.format("IsAdmin: %d %d", queue[2], queue[3]))
            if ok ~= 1 then
                local mod, cksum = et.FindMod(queue[1])
                et.G_Print(string.format("ipcdemo-admin: IPCSend to %s (vm: %d) failed", mod, queue[1]))
            end
        end
    )
    IPCQueue = {}
end

ipcdemo-cmd.lua

-- ipcdemo-cmd.lua
local admin_vm    = -1
local CommandQueue = {}
 
function et_InitGame(levelTime, randomSeed, restart)
    local mod = ""
    local sig = ""
    local i = 1
    while mod ~= nil do
        mod, sig = et.FindMod(i)
        if string.find(mod, "^ipcdemo-admin.lua") == 1 then
            admin_vm = i
            mod      = nil
        end
        i = i + 1
    end
    if admin_vm == -1 then
        et.G_Print("ipcdemo-cmd.lua: Could not find vm number for ipcdemo-admin.lua")
    end
    et.RegisterModname("ipcdemo-cmd.lua")
end
 
function et_IPCReceive(vm, msg)
    if vm == admin_vm then
        local junk1,junk2,level,id = string.find(msg, "IsAdmin:%s+(%d+)%s+(%d)")
        if level ~= nil and id ~= nil then
            runAction(tonumber(id), tonumber(level))
        end
    end
end
 
function runAction(id, level)
    local done = table.foreach(CommandQueue,
        function(i, queue)
            if id == queue[1] then
                if queue[2] <= level then
                    if queue[4] == nil then
                        et.trap_SendConsoleCommand(et.EXEC_INSERT, queue[3])
                    else
                        et.trap_SendConsoleCommand(et.EXEC_INSERT,
                                string.format("%s %s", queue[3], queue[4]))
                    end
                end
                return(i)
            end
        end
    )
    if done ~= nil then
        table.remove(CommandQueue, done)
    end
end
 
function et_ClientCommand(id, command)
    local arg0 = et.trap_Argv(0)
    local arg1 = et.trap_Argv(1)
    if arg0 == "say" then
        if arg1 == "!axis" then
            --          id, lvl, cmd,         argument
            queueCommand(id, 4, "forceteam r", id)
        elseif arg1 == "!allies" then
            queueCommand(id, 4, "forceteam b", id)
        elseif arg1 == "!shuffle" then
            queueCommand(id, 3, "shuffleteamsxp_norestart", nil)
        end
    end
    return(0)
end
 
function queueCommand(id, level, cmd, argument)
    if admin_vm ~= -1 then
        local ok = et.IPCSend(admin_vm, string.format("IsAdmin: %d", id))
        if ok ~= 1 then
            et.G_Print("ipcdemo-cmd: IPCSend to ipcdemo-admin failed")
        else
            table.insert(CommandQueue, { id, level, cmd, argument })
        end
    end
end