ExtraLua mod : my first administrative oriented mod experience :)

User avatar
redcrab
Member
 
Posts: 831
Joined: Tue Dec 13, 2011 13:45

ExtraLua mod : my first administrative oriented mod experience :)

by redcrab » Thu Jun 14, 2012 18:07

This is my first mod. So the code is quite ugly, but I would like to share with you what I' ve done so far.

ExtraLua

The aim is to be able to execute unexpected external lua code at runtime..
For instance ...
-> You want to grant or revoke privs to a player without login/logout yourself (admin) nor modifying auth.txt file and minetest server restart.
-> You would like to change server time or broadcast server messages to players without login yourself (admin)
-> inject new logical behavior on the server without deploying and restarting your minetestserver.
-> etc of the same kind :)..

How to do it?
By placing a brand new lua script file somewhere on your server file system and a minetest mod will load and execute the script file as soon as possible at runtime without restarting the server..

more precisely ...
on server there is bash shell script that manage lua job queue
in minetestserver there is a mod that read job item file and execute it when a particular event occurs : I ve chosen player join event.. but you can choose another event of your choice ... until a "System Signal" will be available in the engine (I'm a bad C programmer :( so I can't propose an engine update )

So firstly the mods/ExtraLua/init.lua file
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
function file_exists(name)
   local f=io.open(name,"r")
   if f~=nil then io.close(f) return true else return false end
end

-- copy paste and modified from chatcommands.lua
function revoke(revokename, revokeprivstr)
        if not revokename or not revokeprivstr then
            return
        end
        local revokeprivs = minetest.string_to_privs(revokeprivstr)
        local privs = minetest.get_player_privs(revokename)
        if revokeprivstr == "all" then
            privs = {}
        else
            for priv, _ in pairs(revokeprivs) do
                privs[priv] = nil
            end
        end
        minetest.set_player_privs(revokename, privs)
    end

-- copy paste and modified from chatcommands.lua
function grant(grantname, grantprivstr)
        if not grantname or not grantprivstr then
            return
        end
        local grantprivs = minetest.string_to_privs(grantprivstr)
        if grantprivstr == "all" then
            grantprivs = minetest.registered_privileges
        end
        local privs = minetest.get_player_privs(grantname)
        local privs_known = true
        for priv, _ in pairs(grantprivs) do
            if not minetest.registered_privileges[priv] then
                privs_known = false
            end
            privs[priv] = true
        end
        if not privs_known then
            return
        end
        minetest.set_player_privs(grantname, privs)
    end

-- job execution temptative each time a player join
minetest.register_on_joinplayer(function(player)
-- minetest.register_on_systemsignal(function(systemsignal)
    luafilename = minetest.get_modpath("ExtraLua").."/job.lua"
    if file_exists(luafilename..".queue") and not file_exists(luafilename) then
        os.rename(luafilename..".queue", luafilename)
    end
        while file_exists(luafilename) do
        strnow = os.date("%Y%m%d-%H%M%S")
        f = loadfile(luafilename)
            if f ~= nil then
            if pcall(f) then
                os.rename(luafilename, luafilename.."."..strnow..".done")
            else
                os.rename(luafilename, luafilename.."."..strnow..".run-error")
            end
        else
            os.rename(luafilename, luafilename.."."..strnow..".compile-error")
        end
        if file_exists(luafilename..".queue") then
            os.rename(luafilename..".queue", luafilename)
        end
    end
    return true
end)



and job quueing command mods/ExtraLua/addjob.sh

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
#!/bin/bash
# TODO : update the following "cd" command with your right ExtraLua mod path
cd  /MinetestServerInstallPath/games/mygamedef/mods/ExtraLua
echo -- `date` >> job.lua.queue
echo $1 >> job.lua.queue
if [ ! -f ./job.lua ]
then
mv ./job.lua.queue ./job.lua
fi
 



addjob example of usage
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
$> ./addjob.sh 'revoke("fooplayer","interact")'
$> ./addjob.sh 'grant("barPlayer","shout")'


when any player will join , the jobs will be executed..

so addjob.sh create or append job.lua.queue lua script you want to execute
job.lua.queue is rename job.lua during its execution by the mod
then job.lua is rename to :
job.lua.TimeStamp.done if ok
job.lua.TimeStamp.compile-error if interpretation syntax error
job.lua.TimeStamp.run-error if runtime execution error

Hope that will help anybody.
Last edited by redcrab on Thu Jun 14, 2012 18:58, edited 1 time in total.
0.4 for serious builder click here
Dedicated Minetest redcrab server forum at http://minetestbb.suret.net

It's nice to be important but it is more important to be nice.
 

User avatar
Calinou
Member
 
Posts: 3124
Joined: Mon Aug 01, 2011 14:26
GitHub: Calinou
IRC: Calinou
In-game: Calinou

by Calinou » Thu Jun 14, 2012 18:52

Great! :D
 

User avatar
sfan5
Member
 
Posts: 3636
Joined: Wed Aug 24, 2011 09:44
GitHub: sfan5
IRC: sfan5

by sfan5 » Thu Jun 14, 2012 19:37

Simple + Useful!
Mods: Mesecons | WorldEdit | Nuke
Minetest builds for Windows (32-bit & 64-bit)
 

celeron55
Member
 
Posts: 430
Joined: Tue Apr 19, 2011 10:10

by celeron55 » Fri Jun 15, 2012 19:32

You could just make it trigger periodically. Eg. a recursive minetest.after() or minetest.register_globalstep() and implement a counter to check it every 5 seconds or so.

I need to add a minetest.register_interval() or something...
 

User avatar
redcrab
Member
 
Posts: 831
Joined: Tue Dec 13, 2011 13:45

by redcrab » Fri Jun 15, 2012 20:26

celeron55 wrote:You could just make it trigger periodically. Eg. a recursive minetest.after() or minetest.register_globalstep() and implement a counter to check it every 5 seconds or so.

I need to add a minetest.register_interval() or something...


Thanks for your comments :D

I would prefer a register_on_signal ... but I don't know if it can be cross platform with Windows (non posix OS)

--> regular polling instead of event ... is an alternative .. but event driven action is cleaner..?

As you guess global step is cpu consuming (invoked every 0.05 s) .. manage a counter then do action for most of the time , nothing... CPU waste

My 2 cents:
May be OS signal may be replace by a "socket" signal (listening port) (client sent an event id to the listening socket, then when minetestserver as recieved the event id close the connection .. or a particular magic UDP packet on a particular port (other than the one used by the client) ...
0.4 for serious builder click here
Dedicated Minetest redcrab server forum at http://minetestbb.suret.net

It's nice to be important but it is more important to be nice.
 


Return to WIP Mods

Who is online

Users browsing this forum: No registered users and 11 guests

cron