forked from VoxeLibre/VoxeLibre
split commands code into separate files
This commit is contained in:
parent
f9a03a3c98
commit
d00a5c74d2
|
@ -0,0 +1,365 @@
|
||||||
|
local S = minetest.get_translator("mcl_commands")
|
||||||
|
|
||||||
|
local mod_death_messages = minetest.get_modpath("mcl_death_messages")
|
||||||
|
|
||||||
|
local parse_json = minetest.parse_json
|
||||||
|
local get_modpath = minetest.get_modpath
|
||||||
|
|
||||||
|
mcl_commands.types = {
|
||||||
|
pos = {"%(? *(%-?[%d.]+) *,? *(%-?[%d.]+) *,? *(%-?[%d.]+) *%)?",
|
||||||
|
function(res, pointer)
|
||||||
|
local pos = {
|
||||||
|
x = tonumber(res[pointer]),
|
||||||
|
y = tonumber(res[pointer + 1]),
|
||||||
|
z = tonumber(res[pointer + 2])
|
||||||
|
}
|
||||||
|
if pos.x and pos.y and pos.z then
|
||||||
|
return nil, pos, pointer+3
|
||||||
|
else
|
||||||
|
return S("Pos is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
text = {"(.+)",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] == tostring(res[pointer]) then
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Text is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
number = {"(%-?[%d.]+)}",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] == tonumber(res[pointer]) then
|
||||||
|
return nil, tonumber(res[pointer]), pointer+1
|
||||||
|
else
|
||||||
|
return S("Number is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
int = {"(%-?[%d]+)}",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] == math.floor(tonumber(res[pointer])) then
|
||||||
|
return nil, tonumber(res[pointer]), pointer+1
|
||||||
|
else
|
||||||
|
return S("Int is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
word = {"([^ ]+)",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] == tostring(res[pointer]) then
|
||||||
|
return nil, tostring(res[pointer]), pointer+1
|
||||||
|
else
|
||||||
|
return S("Word is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
alpha = {"([A-Za-z]+)}",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] then
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Alpha is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
modname = {"([a-z0-9_]+)}",
|
||||||
|
function(res, pointer)
|
||||||
|
if get_modpath(res[pointer]) then
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Modname is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
alphascore = {"([A-Za-z_]+)",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] then --What is alphascore?
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Alphascore is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
alphanumeric = {"([A-Za-z0-9]+)}",
|
||||||
|
function(res, pointer)
|
||||||
|
if res[pointer] then --What is alphanumerical?
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Alphanumerical is invalid!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
username = {"([A-Za-z0-9-_]+)",
|
||||||
|
function(res, pointer)
|
||||||
|
--if minetest.player_exists(res[pointer]) then
|
||||||
|
if res[pointer] then
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Player doesn't exist.")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
target = {"([A-Za-z0-9-_]+)",
|
||||||
|
function(res, pointer)
|
||||||
|
--if minetest.player_exists(res[pointer]) then
|
||||||
|
if res[pointer] then
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Player doesn't exist.")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
json = {"(.+)", --FIXME
|
||||||
|
function(res, pointer)
|
||||||
|
local parsed = parse_json(res[pointer])
|
||||||
|
if parsed then
|
||||||
|
return nil, parsed, pointer+1
|
||||||
|
else
|
||||||
|
return S("Json failed to parse!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
color = {"([^ ]+)", --FIXME
|
||||||
|
function(res, pointer)
|
||||||
|
local color = mcl_util.get_color(res[pointer])
|
||||||
|
if color then
|
||||||
|
return nil, color, pointer+1
|
||||||
|
else
|
||||||
|
return S("Color is not a valid color name or hexadecimal!")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
nodename = {"(%l+[%w_]+%:?[_%l]+[%w_]*)",
|
||||||
|
function(res, pointer)
|
||||||
|
if minetest.registered_items[res[pointer]] then
|
||||||
|
return nil, res[pointer], pointer+1
|
||||||
|
else
|
||||||
|
return S("Nodename is invalid")
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
}
|
||||||
|
|
||||||
|
function mcl_commands.register_command(name, def)
|
||||||
|
def = def or {}
|
||||||
|
local cmd = mcl_commands.build(name, def)
|
||||||
|
if minetest.registered_chatcommands[name] then
|
||||||
|
error("[mcl_commands] Failed to register command: ["..name.."] command already existing! Use mcl_commands.overide_command() if you want to overide existing command")
|
||||||
|
end
|
||||||
|
minetest.register_chatcommand(name, cmd)
|
||||||
|
minetest.log("action", "[mcl_commands] ["..name.."] command registered successfully")
|
||||||
|
return cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_commands.override_command(name, def)
|
||||||
|
def = def or {}
|
||||||
|
local cmd = mcl_commands.build(name, def)
|
||||||
|
if minetest.registered_chatcommands[name] then
|
||||||
|
minetest.unregister_chatcommand(name)
|
||||||
|
end
|
||||||
|
minetest.register_chatcommand(name, cmd)
|
||||||
|
minetest.log("action", "[mcl_commands] ["..name.."] command overridden successfully")
|
||||||
|
return cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
local STATE_READY = 1
|
||||||
|
local STATE_PARAM = 2
|
||||||
|
local STATE_PARAM_TYPE = 3
|
||||||
|
local bad_chars = {"(", ")", ".", "%", "+", "-", "*", "?", "[", "^", "$"}
|
||||||
|
local function escape(char)
|
||||||
|
if bad_chars[char] then
|
||||||
|
return "%" .. char
|
||||||
|
else
|
||||||
|
return char
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dprint = function() end
|
||||||
|
|
||||||
|
function mcl_commands.build(name, chat_def)
|
||||||
|
local cmd = {
|
||||||
|
_subs = {}
|
||||||
|
}
|
||||||
|
function cmd:sub(route, def)
|
||||||
|
dprint("Parsing " .. route)
|
||||||
|
|
||||||
|
if string.trim then
|
||||||
|
route = string.trim(route)
|
||||||
|
end
|
||||||
|
|
||||||
|
local sub = {
|
||||||
|
pattern = "^",
|
||||||
|
params = {},
|
||||||
|
func = def.func,
|
||||||
|
privs = def.privs or {},
|
||||||
|
desc = def.desc,
|
||||||
|
params_desc = def.params or "",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- End of param reached: add it to the pattern
|
||||||
|
local param = ""
|
||||||
|
local param_type = ""
|
||||||
|
local should_be_eos = false
|
||||||
|
local function finishParam()
|
||||||
|
if param ~= "" and param_type ~= "" then
|
||||||
|
dprint(" - Found param " .. param .. " type " .. param_type)
|
||||||
|
|
||||||
|
local pattern = mcl_commands.types[param_type][1]
|
||||||
|
if not pattern then
|
||||||
|
error("Unrecognised param_type=" .. param_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
sub.pattern = sub.pattern .. pattern
|
||||||
|
|
||||||
|
table.insert(sub.params, param_type)
|
||||||
|
|
||||||
|
param = ""
|
||||||
|
param_type = ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Iterate through the route to find params
|
||||||
|
local state = STATE_READY
|
||||||
|
local catching_space = false
|
||||||
|
local match_space = " " -- change to "%s" to also catch tabs and newlines
|
||||||
|
local catch_space = match_space.."+"
|
||||||
|
for i = 1, #route do
|
||||||
|
local c = route:sub(i, i)
|
||||||
|
if should_be_eos then
|
||||||
|
error("Should be end of string. Nothing is allowed after a param of type text.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if state == STATE_READY then
|
||||||
|
if c == ":" then
|
||||||
|
dprint(" - Found :, entering param")
|
||||||
|
state = STATE_PARAM
|
||||||
|
param_type = "word"
|
||||||
|
catching_space = false
|
||||||
|
elseif c:match(match_space) then
|
||||||
|
print(" - Found space")
|
||||||
|
if not catching_space then
|
||||||
|
catching_space = true
|
||||||
|
sub.pattern = sub.pattern .. catch_space
|
||||||
|
end
|
||||||
|
else
|
||||||
|
catching_space = false
|
||||||
|
sub.pattern = sub.pattern .. escape(c)
|
||||||
|
end
|
||||||
|
elseif state == STATE_PARAM then
|
||||||
|
if c == ":" then
|
||||||
|
dprint(" - Found :, entering param type")
|
||||||
|
state = STATE_PARAM_TYPE
|
||||||
|
param_type = ""
|
||||||
|
elseif c:match(match_space) then
|
||||||
|
print(" - Found whitespace, leaving param")
|
||||||
|
state = STATE_READY
|
||||||
|
finishParam()
|
||||||
|
catching_space = true
|
||||||
|
sub.pattern = sub.pattern .. catch_space
|
||||||
|
elseif c:match("%W") then
|
||||||
|
dprint(" - Found nonalphanum, leaving param")
|
||||||
|
state = STATE_READY
|
||||||
|
finishParam()
|
||||||
|
sub.pattern = sub.pattern .. escape(c)
|
||||||
|
else
|
||||||
|
param = param .. c
|
||||||
|
end
|
||||||
|
elseif state == STATE_PARAM_TYPE then
|
||||||
|
if c:match(match_space) then
|
||||||
|
print(" - Found space, leaving param type")
|
||||||
|
state = STATE_READY
|
||||||
|
finishParam()
|
||||||
|
catching_space = true
|
||||||
|
sub.pattern = sub.pattern .. catch_space
|
||||||
|
elseif c:match("%W") then
|
||||||
|
dprint(" - Found nonalphanum, leaving param type")
|
||||||
|
state = STATE_READY
|
||||||
|
finishParam()
|
||||||
|
sub.pattern = sub.pattern .. escape(c)
|
||||||
|
else
|
||||||
|
param_type = param_type .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dprint(" - End of route")
|
||||||
|
finishParam()
|
||||||
|
sub.pattern = sub.pattern .. "$"
|
||||||
|
dprint("Pattern: " .. sub.pattern)
|
||||||
|
|
||||||
|
table.insert(self._subs, sub)
|
||||||
|
end
|
||||||
|
|
||||||
|
if chat_def.func then
|
||||||
|
chat_def.func(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd.func = function(name, param)
|
||||||
|
local msg
|
||||||
|
for i = 1, #cmd._subs do
|
||||||
|
local sub = cmd._subs[i]
|
||||||
|
local res = { string.match(param, sub.pattern) }
|
||||||
|
if #res > 0 then
|
||||||
|
local pointer = 1
|
||||||
|
local params = { name }
|
||||||
|
for j = 1, #sub.params do
|
||||||
|
local param = sub.params[j]
|
||||||
|
local value
|
||||||
|
if mcl_commands.types[param] then
|
||||||
|
msg, value, pointer = mcl_commands.check_type(param, res, pointer)
|
||||||
|
table.insert(params, value)
|
||||||
|
else
|
||||||
|
table.insert(params, res[pointer])
|
||||||
|
pointer = pointer + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local can_execute, missing_privs = minetest.check_player_privs(name, sub.privs)
|
||||||
|
if can_execute then
|
||||||
|
if table.unpack then
|
||||||
|
-- lua 5.2 or later
|
||||||
|
return sub.func(table.unpack(params))
|
||||||
|
else
|
||||||
|
-- lua 5.1 or earlier
|
||||||
|
return sub.func(unpack(params))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local missing_privs_str = ""
|
||||||
|
for i = 1, #missing_privs do
|
||||||
|
if not i == #missing_privs then
|
||||||
|
missing_privs_str = missing_privs_str..missing_privs[i].." "
|
||||||
|
else
|
||||||
|
missing_privs_str = missing_privs_str..missing_privs[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false, "You don't have permission to run this command (missing privilege: "..missing_privs_str..")"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false, msg
|
||||||
|
end
|
||||||
|
if chat_def.params then
|
||||||
|
cmd.params = chat_def.params
|
||||||
|
else
|
||||||
|
cmd.params = ""
|
||||||
|
end
|
||||||
|
cmd.privs = chat_def.privs
|
||||||
|
cmd.description = chat_def.description
|
||||||
|
return cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_commands.check_type(type, res, pointer)
|
||||||
|
return mcl_commands.types[type][2](res, pointer)
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_commands.register_chatcommand_alias(alias, cmd, bypass)
|
||||||
|
if not bypass then bypass = false end
|
||||||
|
if minetest.registered_chatcommands[alias] then
|
||||||
|
minetest.log("warning", "[mcl_commands] trying to alias ["..cmd.."] to already existing ["..alias.."] command")
|
||||||
|
elseif minetest.settings:get_bool("mcl_builtin_commands_overide", true) or bypass then
|
||||||
|
minetest.register_chatcommand(alias, minetest.chatcommands[cmd])
|
||||||
|
minetest.log("action", "[mcl_commands] ["..cmd.."] command aliased successfully to ["..alias.."]")
|
||||||
|
else
|
||||||
|
minetest.log("action", "[mcl_commands] ["..cmd.."] command not aliased to ["..alias.."]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_commands.rename_chatcommand(newname, cmd, bypass)
|
||||||
|
if not bypass then bypass = false end
|
||||||
|
if minetest.registered_chatcommands[newname] then
|
||||||
|
minetest.log("warning", "[mcl_commands] trying to rename ["..cmd.."] to already existing ["..alias.."] command")
|
||||||
|
elseif minetest.settings:get_bool("mcl_builtin_commands_overide", true) or bypass then
|
||||||
|
minetest.register_chatcommand(newname, minetest.chatcommands[cmd])
|
||||||
|
minetest.unregister_chatcommand(cmd)
|
||||||
|
minetest.log("action", "[mcl_commands] ["..cmd.."] command renamed successfully to ["..newname.."]")
|
||||||
|
else
|
||||||
|
minetest.log("action", "[mcl_commands] ["..cmd.."] command not renamed to ["..newname.."]")
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,403 +7,7 @@ local mod_death_messages = minetest.get_modpath("mcl_death_messages")
|
||||||
|
|
||||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
local parse_json = minetest.parse_json
|
|
||||||
local get_modpath = minetest.get_modpath
|
|
||||||
|
|
||||||
mcl_commands = {}
|
mcl_commands = {}
|
||||||
|
|
||||||
mcl_commands.types = {
|
dofile(modpath.."/api.lua")
|
||||||
pos = {"%(? *(%-?[%d.]+) *,? *(%-?[%d.]+) *,? *(%-?[%d.]+) *%)?",
|
dofile(modpath.."/utils.lua")
|
||||||
function(res, pointer)
|
|
||||||
local pos = {
|
|
||||||
x = tonumber(res[pointer]),
|
|
||||||
y = tonumber(res[pointer + 1]),
|
|
||||||
z = tonumber(res[pointer + 2])
|
|
||||||
}
|
|
||||||
if pos.x and pos.y and pos.z then
|
|
||||||
return nil, pos, pointer+3
|
|
||||||
else
|
|
||||||
return S("Pos is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
text = {"(.+)",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] == tostring(res[pointer]) then
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Text is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
number = {"(%-?[%d.]+)}",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] == tonumber(res[pointer]) then
|
|
||||||
return nil, tonumber(res[pointer]), pointer+1
|
|
||||||
else
|
|
||||||
return S("Number is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
int = {"(%-?[%d]+)}",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] == math.floor(tonumber(res[pointer])) then
|
|
||||||
return nil, tonumber(res[pointer]), pointer+1
|
|
||||||
else
|
|
||||||
return S("Int is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
word = {"([^ ]+)",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] == tostring(res[pointer]) then
|
|
||||||
return nil, tostring(res[pointer]), pointer+1
|
|
||||||
else
|
|
||||||
return S("Word is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
alpha = {"([A-Za-z]+)}",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] then
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Alpha is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
modname = {"([a-z0-9_]+)}",
|
|
||||||
function(res, pointer)
|
|
||||||
if get_modpath(res[pointer]) then
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Modname is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
alphascore = {"([A-Za-z_]+)",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] then --What is alphascore?
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Alphascore is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
alphanumeric = {"([A-Za-z0-9]+)}",
|
|
||||||
function(res, pointer)
|
|
||||||
if res[pointer] then --What is alphanumerical?
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Alphanumerical is invalid!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
username = {"([A-Za-z0-9-_]+)",
|
|
||||||
function(res, pointer)
|
|
||||||
--if minetest.player_exists(res[pointer]) then
|
|
||||||
if res[pointer] then
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Player doesn't exist.")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
target = {"([A-Za-z0-9-_]+)",
|
|
||||||
function(res, pointer)
|
|
||||||
--if minetest.player_exists(res[pointer]) then
|
|
||||||
if res[pointer] then
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Player doesn't exist.")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
json = {"(.+)", --FIXME
|
|
||||||
function(res, pointer)
|
|
||||||
local parsed = parse_json(res[pointer])
|
|
||||||
if parsed then
|
|
||||||
return nil, parsed, pointer+1
|
|
||||||
else
|
|
||||||
return S("Json failed to parse!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
color = {"([^ ]+)", --FIXME
|
|
||||||
function(res, pointer)
|
|
||||||
local color = mcl_util.get_color(res[pointer])
|
|
||||||
if color then
|
|
||||||
return nil, color, pointer+1
|
|
||||||
else
|
|
||||||
return S("Color is not a valid color name or hexadecimal!")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
nodename = {"(%l+[%w_]+%:?[_%l]+[%w_]*)",
|
|
||||||
function(res, pointer)
|
|
||||||
if minetest.registered_items[res[pointer]] then
|
|
||||||
return nil, res[pointer], pointer+1
|
|
||||||
else
|
|
||||||
return S("Nodename is invalid")
|
|
||||||
end
|
|
||||||
end},
|
|
||||||
}
|
|
||||||
|
|
||||||
function mcl_commands.register_command(name, def)
|
|
||||||
def = def or {}
|
|
||||||
local cmd = mcl_commands.build(name, def)
|
|
||||||
if minetest.registered_chatcommands[name] then
|
|
||||||
error("[mcl_commands] Failed to register command: ["..name.."] command already existing! Use mcl_commands.overide_command() if you want to overide existing command")
|
|
||||||
end
|
|
||||||
minetest.register_chatcommand(name, cmd)
|
|
||||||
minetest.log("action", "[mcl_commands] ["..name.."] command registered successfully")
|
|
||||||
return cmd
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_commands.override_command(name, def)
|
|
||||||
def = def or {}
|
|
||||||
local cmd = mcl_commands.build(name, def)
|
|
||||||
if minetest.registered_chatcommands[name] then
|
|
||||||
minetest.unregister_chatcommand(name)
|
|
||||||
end
|
|
||||||
minetest.register_chatcommand(name, cmd)
|
|
||||||
minetest.log("action", "[mcl_commands] ["..name.."] command overridden successfully")
|
|
||||||
return cmd
|
|
||||||
end
|
|
||||||
|
|
||||||
local STATE_READY = 1
|
|
||||||
local STATE_PARAM = 2
|
|
||||||
local STATE_PARAM_TYPE = 3
|
|
||||||
local bad_chars = {"(", ")", ".", "%", "+", "-", "*", "?", "[", "^", "$"}
|
|
||||||
local function escape(char)
|
|
||||||
if bad_chars[char] then
|
|
||||||
return "%" .. char
|
|
||||||
else
|
|
||||||
return char
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local dprint = function() end
|
|
||||||
|
|
||||||
function mcl_commands.build(name, chat_def)
|
|
||||||
local cmd = {
|
|
||||||
_subs = {}
|
|
||||||
}
|
|
||||||
function cmd:sub(route, def)
|
|
||||||
dprint("Parsing " .. route)
|
|
||||||
|
|
||||||
if string.trim then
|
|
||||||
route = string.trim(route)
|
|
||||||
end
|
|
||||||
|
|
||||||
local sub = {
|
|
||||||
pattern = "^",
|
|
||||||
params = {},
|
|
||||||
func = def.func,
|
|
||||||
privs = def.privs or {},
|
|
||||||
desc = def.desc,
|
|
||||||
params_desc = def.params or "",
|
|
||||||
}
|
|
||||||
|
|
||||||
-- End of param reached: add it to the pattern
|
|
||||||
local param = ""
|
|
||||||
local param_type = ""
|
|
||||||
local should_be_eos = false
|
|
||||||
local function finishParam()
|
|
||||||
if param ~= "" and param_type ~= "" then
|
|
||||||
dprint(" - Found param " .. param .. " type " .. param_type)
|
|
||||||
|
|
||||||
local pattern = mcl_commands.types[param_type][1]
|
|
||||||
if not pattern then
|
|
||||||
error("Unrecognised param_type=" .. param_type)
|
|
||||||
end
|
|
||||||
|
|
||||||
sub.pattern = sub.pattern .. pattern
|
|
||||||
|
|
||||||
table.insert(sub.params, param_type)
|
|
||||||
|
|
||||||
param = ""
|
|
||||||
param_type = ""
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Iterate through the route to find params
|
|
||||||
local state = STATE_READY
|
|
||||||
local catching_space = false
|
|
||||||
local match_space = " " -- change to "%s" to also catch tabs and newlines
|
|
||||||
local catch_space = match_space.."+"
|
|
||||||
for i = 1, #route do
|
|
||||||
local c = route:sub(i, i)
|
|
||||||
if should_be_eos then
|
|
||||||
error("Should be end of string. Nothing is allowed after a param of type text.")
|
|
||||||
end
|
|
||||||
|
|
||||||
if state == STATE_READY then
|
|
||||||
if c == ":" then
|
|
||||||
dprint(" - Found :, entering param")
|
|
||||||
state = STATE_PARAM
|
|
||||||
param_type = "word"
|
|
||||||
catching_space = false
|
|
||||||
elseif c:match(match_space) then
|
|
||||||
print(" - Found space")
|
|
||||||
if not catching_space then
|
|
||||||
catching_space = true
|
|
||||||
sub.pattern = sub.pattern .. catch_space
|
|
||||||
end
|
|
||||||
else
|
|
||||||
catching_space = false
|
|
||||||
sub.pattern = sub.pattern .. escape(c)
|
|
||||||
end
|
|
||||||
elseif state == STATE_PARAM then
|
|
||||||
if c == ":" then
|
|
||||||
dprint(" - Found :, entering param type")
|
|
||||||
state = STATE_PARAM_TYPE
|
|
||||||
param_type = ""
|
|
||||||
elseif c:match(match_space) then
|
|
||||||
print(" - Found whitespace, leaving param")
|
|
||||||
state = STATE_READY
|
|
||||||
finishParam()
|
|
||||||
catching_space = true
|
|
||||||
sub.pattern = sub.pattern .. catch_space
|
|
||||||
elseif c:match("%W") then
|
|
||||||
dprint(" - Found nonalphanum, leaving param")
|
|
||||||
state = STATE_READY
|
|
||||||
finishParam()
|
|
||||||
sub.pattern = sub.pattern .. escape(c)
|
|
||||||
else
|
|
||||||
param = param .. c
|
|
||||||
end
|
|
||||||
elseif state == STATE_PARAM_TYPE then
|
|
||||||
if c:match(match_space) then
|
|
||||||
print(" - Found space, leaving param type")
|
|
||||||
state = STATE_READY
|
|
||||||
finishParam()
|
|
||||||
catching_space = true
|
|
||||||
sub.pattern = sub.pattern .. catch_space
|
|
||||||
elseif c:match("%W") then
|
|
||||||
dprint(" - Found nonalphanum, leaving param type")
|
|
||||||
state = STATE_READY
|
|
||||||
finishParam()
|
|
||||||
sub.pattern = sub.pattern .. escape(c)
|
|
||||||
else
|
|
||||||
param_type = param_type .. c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
dprint(" - End of route")
|
|
||||||
finishParam()
|
|
||||||
sub.pattern = sub.pattern .. "$"
|
|
||||||
dprint("Pattern: " .. sub.pattern)
|
|
||||||
|
|
||||||
table.insert(self._subs, sub)
|
|
||||||
end
|
|
||||||
|
|
||||||
if chat_def.func then
|
|
||||||
chat_def.func(cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
cmd.func = function(name, param)
|
|
||||||
local msg
|
|
||||||
for i = 1, #cmd._subs do
|
|
||||||
local sub = cmd._subs[i]
|
|
||||||
local res = { string.match(param, sub.pattern) }
|
|
||||||
if #res > 0 then
|
|
||||||
local pointer = 1
|
|
||||||
local params = { name }
|
|
||||||
for j = 1, #sub.params do
|
|
||||||
local param = sub.params[j]
|
|
||||||
local value
|
|
||||||
if mcl_commands.types[param] then
|
|
||||||
msg, value, pointer = mcl_commands.check_type(param, res, pointer)
|
|
||||||
table.insert(params, value)
|
|
||||||
else
|
|
||||||
table.insert(params, res[pointer])
|
|
||||||
pointer = pointer + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local can_execute, missing_privs = minetest.check_player_privs(name, sub.privs)
|
|
||||||
if can_execute then
|
|
||||||
if table.unpack then
|
|
||||||
-- lua 5.2 or later
|
|
||||||
return sub.func(table.unpack(params))
|
|
||||||
else
|
|
||||||
-- lua 5.1 or earlier
|
|
||||||
return sub.func(unpack(params))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local missing_privs_str = ""
|
|
||||||
for i = 1, #missing_privs do
|
|
||||||
if not i == #missing_privs then
|
|
||||||
missing_privs_str = missing_privs_str..missing_privs[i].." "
|
|
||||||
else
|
|
||||||
missing_privs_str = missing_privs_str..missing_privs[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, "You don't have permission to run this command (missing privilege: "..missing_privs_str..")"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, msg
|
|
||||||
end
|
|
||||||
if chat_def.params then
|
|
||||||
cmd.params = chat_def.params
|
|
||||||
else
|
|
||||||
cmd.params = ""
|
|
||||||
end
|
|
||||||
cmd.privs = chat_def.privs
|
|
||||||
cmd.description = chat_def.description
|
|
||||||
return cmd
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_commands.check_type(type, res, pointer)
|
|
||||||
return mcl_commands.types[type][2](res, pointer)
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_commands.register_chatcommand_alias(alias, cmd, bypass)
|
|
||||||
if not bypass then bypass = false end
|
|
||||||
if minetest.registered_chatcommands[alias] then
|
|
||||||
minetest.log("warning", "[mcl_commands] trying to alias ["..cmd.."] to already existing ["..alias.."] command")
|
|
||||||
elseif minetest.settings:get_bool("mcl_builtin_commands_overide", true) or bypass then
|
|
||||||
minetest.register_chatcommand(alias, minetest.chatcommands[cmd])
|
|
||||||
minetest.log("action", "[mcl_commands] ["..cmd.."] command aliased successfully to ["..alias.."]")
|
|
||||||
else
|
|
||||||
minetest.log("action", "[mcl_commands] ["..cmd.."] command not aliased to ["..alias.."]")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_commands.rename_chatcommand(newname, cmd, bypass)
|
|
||||||
if not bypass then bypass = false end
|
|
||||||
if minetest.registered_chatcommands[newname] then
|
|
||||||
minetest.log("warning", "[mcl_commands] trying to rename ["..cmd.."] to already existing ["..alias.."] command")
|
|
||||||
elseif minetest.settings:get_bool("mcl_builtin_commands_overide", true) or bypass then
|
|
||||||
minetest.register_chatcommand(newname, minetest.chatcommands[cmd])
|
|
||||||
minetest.unregister_chatcommand(cmd)
|
|
||||||
minetest.log("action", "[mcl_commands] ["..cmd.."] command renamed successfully to ["..newname.."]")
|
|
||||||
else
|
|
||||||
minetest.log("action", "[mcl_commands] ["..cmd.."] command not renamed to ["..newname.."]")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function mcl_commands.get_target_selector(target, pos, name)
|
|
||||||
if minetest.player_exists(target) then
|
|
||||||
return minetest.get_player_by_name(target)
|
|
||||||
elseif target == "@a" then
|
|
||||||
return nil, minetest.get_connected_players()
|
|
||||||
elseif target == "@r" then
|
|
||||||
local connected = minetest.get_connected_players()
|
|
||||||
return nil, connected[math.random(1, #connected)]
|
|
||||||
elseif target == "@s" then
|
|
||||||
if name then
|
|
||||||
local player = minetest.get_player_by_name(name)
|
|
||||||
end
|
|
||||||
if player then
|
|
||||||
return nil, player
|
|
||||||
else
|
|
||||||
return S("Not a valid player")
|
|
||||||
end
|
|
||||||
elseif target == "@p" then
|
|
||||||
local smallest = math.huge
|
|
||||||
local nearest
|
|
||||||
for _,player in pairs(minetest.get_connected_players()) do
|
|
||||||
local distance = vector.distance(pos, player:get_pos())
|
|
||||||
if distance < min_distance then
|
|
||||||
min_distance = distance
|
|
||||||
nearest = player
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if nearest then
|
|
||||||
return nil, nearest
|
|
||||||
else
|
|
||||||
return S("No player online")
|
|
||||||
end
|
|
||||||
elseif target == "@e" then
|
|
||||||
return minetest.luaentities --TODO: add filtering of not valid entities.
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
local S = minetest.get_translator("mcl_commands")
|
||||||
|
|
||||||
|
function mcl_commands.get_target_selector(target, pos, name)
|
||||||
|
if minetest.player_exists(target) then
|
||||||
|
return minetest.get_player_by_name(target)
|
||||||
|
elseif target == "@a" then
|
||||||
|
return nil, minetest.get_connected_players()
|
||||||
|
elseif target == "@r" then
|
||||||
|
local connected = minetest.get_connected_players()
|
||||||
|
return nil, connected[math.random(1, #connected)]
|
||||||
|
elseif target == "@s" then
|
||||||
|
if name then
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
end
|
||||||
|
if player then
|
||||||
|
return nil, player
|
||||||
|
else
|
||||||
|
return S("Not a valid player")
|
||||||
|
end
|
||||||
|
elseif target == "@p" then
|
||||||
|
local smallest = math.huge
|
||||||
|
local nearest
|
||||||
|
for _,player in pairs(minetest.get_connected_players()) do
|
||||||
|
local distance = vector.distance(pos, player:get_pos())
|
||||||
|
if distance < min_distance then
|
||||||
|
min_distance = distance
|
||||||
|
nearest = player
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if nearest then
|
||||||
|
return nil, nearest
|
||||||
|
else
|
||||||
|
return S("No player online")
|
||||||
|
end
|
||||||
|
elseif target == "@e" then
|
||||||
|
return minetest.luaentities --TODO: add filtering of not valid entities.
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
mcl_util.registered_blacklisted_entities = {}
|
||||||
|
function mcl_util.register_blacklisted_entities(type)
|
||||||
|
mcl_util.registered_blacklisted_entities[type] = true
|
||||||
|
end
|
||||||
|
function mcl_util.get_real_entities()
|
||||||
|
for key, val in pairs(minetest.luaentities) do
|
||||||
|
local def = minetest.registered_entities[minetest.luaentities[key].name]
|
||||||
|
if not mcl_util.registered_blacklisted_entities[def.type] then
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,3 +1,5 @@
|
||||||
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
mcl_util = {}
|
mcl_util = {}
|
||||||
|
|
||||||
-- Based on minetest.rotate_and_place
|
-- Based on minetest.rotate_and_place
|
||||||
|
@ -418,3 +420,5 @@ function mcl_util.get_color(colorstr)
|
||||||
return colorstr, hex
|
return colorstr, hex
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
dofile(modpath.."/entities.lua")
|
Loading…
Reference in New Issue