split commands code into separate files

This commit is contained in:
AFCMS 2021-03-31 19:04:24 +02:00
parent f9a03a3c98
commit d00a5c74d2
5 changed files with 420 additions and 398 deletions

View File

@ -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

View File

@ -7,403 +7,7 @@ local mod_death_messages = minetest.get_modpath("mcl_death_messages")
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.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
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
dofile(modpath.."/api.lua")
dofile(modpath.."/utils.lua")

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,5 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
mcl_util = {}
-- Based on minetest.rotate_and_place
@ -418,3 +420,5 @@ function mcl_util.get_color(colorstr)
return colorstr, hex
end
end
dofile(modpath.."/entities.lua")