From b9ffb5f30d64d365e6792d0d3acff552d9fcd0fd Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 30 Mar 2012 01:45:23 +0300 Subject: [PATCH] minetest.register_chatcommand(cmd, def) --- builtin/builtin.lua | 110 ++++++++++++++++++++++++++++++++++++++++++ doc/lua_api.txt | 9 ++++ src/auth.cpp | 6 +++ src/servercommand.cpp | 21 +------- 4 files changed, 126 insertions(+), 20 deletions(-) diff --git a/builtin/builtin.lua b/builtin/builtin.lua index 2be7a4dcf..71cd4cf53 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -821,6 +821,116 @@ function minetest.after(time, func, param) table.insert(minetest.timers_to_add, {time=time, func=func, param=param}) end +function minetest.check_player_privs(name, privs) + local player_privs = minetest.get_player_privs(name) + local missing_privileges = {} + for priv, val in pairs(privs) do + if val then + if not player_privs[priv] then + table.insert(missing_privileges, priv) + end + end + end + if #missing_privileges > 0 then + return false, missing_privileges + end + return true, "" +end + +-- +-- Chat commands +-- + +minetest.chatcommands = {} +function minetest.register_chatcommand(cmd, def) + def = def or {} + def.params = def.params or "" + def.description = def.description or "" + def.privs = def.privs or {} + minetest.chatcommands[cmd] = def +end + +-- Register the help command +minetest.register_chatcommand("help", { + privs = {}, + params = "(nothing)/all/", + description = "Get help for commands", + func = function(name, param) + local format_help_line = function(cmd, def) + local msg = "/"..cmd + if def.params and def.params ~= "" then msg = msg .. " " .. def.params end + if def.description and def.description ~= "" then msg = msg .. ": " .. def.description end + return msg + end + if not param or param == "" then + local msg = "" + cmds = {} + for cmd, def in pairs(minetest.chatcommands) do + if minetest.check_player_privs(name, def.privs) then + table.insert(cmds, cmd) + end + end + minetest.chat_send_player(name, "Available commands: "..table.concat(cmds, " ")) + minetest.chat_send_player(name, "Use '/help ' to get more information, or '/help all' to list everything.") + elseif param == "all" then + minetest.chat_send_player(name, "Available commands:") + for cmd, def in pairs(minetest.chatcommands) do + if minetest.check_player_privs(name, def.privs) then + minetest.chat_send_player(name, format_help_line(cmd, def)) + end + end + else + local cmd = param + def = minetest.chatcommands[cmd] + if not def then + minetest.chat_send_player(name, "Command not available: "..cmd) + else + minetest.chat_send_player(name, format_help_line(cmd, def)) + end + end + end, +}) + +-- Register C++ commands without functions +minetest.register_chatcommand("me", {params = nil, description = "chat action (eg. /me orders a pizza)"}) +minetest.register_chatcommand("status", {description = "print server status line"}) +minetest.register_chatcommand("privs", {params = "", description = "print out privileges of player"}) +minetest.register_chatcommand("shutdown", {params = "", description = "shutdown server", privs = {server=true}}) +minetest.register_chatcommand("setting", {params = " = ", description = "set line in configuration file", privs = {server=true}}) +minetest.register_chatcommand("clearobjects", {params = "", description = "clear all objects in world", privs = {server=true}}) +minetest.register_chatcommand("time", {params = "<0...24000>", description = "set time of day", privs = {settime=true}}) +minetest.register_chatcommand("teleport", {params = ",,", description = "teleport to given position", privs = {teleport=true}}) +minetest.register_chatcommand("grant", {params = " ", description = "Give privilege to player", privs = {privs=true}}) +minetest.register_chatcommand("revoke", {params = " ", description = "Remove privilege from player", privs = {privs=true}}) +minetest.register_chatcommand("ban", {params = "", description = "ban IP of player", privs = {ban=true}}) +minetest.register_chatcommand("unban", {params = "", description = "remove IP ban", privs = {ban=true}}) +minetest.register_chatcommand("setpassword", {params = " ", description = "set given password", privs = {password=true}}) +minetest.register_chatcommand("clearpassword", {params = "", description = "set empty password", privs = {password=true}}) + +-- +-- Builtin chat handler +-- + +minetest.register_on_chat_message(function(name, message) + local cmd, param = string.match(message, "/([^ ]+) *(.*)") + local cmd_def = minetest.chatcommands[cmd] + if cmd_def then + if not cmd_def.func then + -- This is a C++ command + return false + else + local has_privs, missing_privs = minetest.check_player_privs(name, cmd_def.privs) + if has_privs then + cmd_def.func(name, param) + else + minetest.chat_send_player(name, "You don't have permission to run this command (missing privileges: "..table.concat(missing_privs, ", ")..")") + end + return true -- handled chat message + end + end + return false +end) + -- -- Set random seed -- diff --git a/doc/lua_api.txt b/doc/lua_api.txt index caa5514b7..740f73b07 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -499,6 +499,7 @@ minetest.register_on_respawnplayer(func(ObjectRef)) ^ return true in func to disable regular player placement ^ currently called _before_ repositioning of player occurs minetest.register_on_chat_message(func(name, message)) +minetest.register_chatcommand(cmd, chatcommand definition) minetest.add_to_creative_inventory(itemstring) minetest.setting_get(name) -> string or nil @@ -507,6 +508,7 @@ minetest.setting_getbool(name) -> boolean value or nil minetest.chat_send_all(text) minetest.chat_send_player(name, text) minetest.get_player_privs(name) -> set of privs +minetest.check_player_privs(name, {priv1=true,...}) -> bool, missing_privs minetest.get_inventory(location) -> InvRef ^ location = eg. {type="player", name="celeron55"} {type="node", pos={x=, y=, z=}} @@ -858,4 +860,11 @@ Recipe (furnace fuel): burntime = 1, } +Chatcommand definition (register_chatcommand) +{ + params = " ", -- short parameter description + description = "Remove privilege from player", -- full description + privs = {privs=true}}, -- require the "privs" privilege to run + func = function(name, param), -- called when command is run +} diff --git a/src/auth.cpp b/src/auth.cpp index fce521e13..cafeb38d4 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -36,6 +36,8 @@ std::set privsToSet(u64 privs) s.insert("settime"); if(privs & PRIV_PRIVS) s.insert("privs"); + if(privs & PRIV_SERVER) + s.insert("server"); if(privs & PRIV_SHOUT) s.insert("shout"); if(privs & PRIV_BAN) @@ -60,6 +62,8 @@ std::string privsToString(u64 privs) os<<"settime,"; if(privs & PRIV_PRIVS) os<<"privs,"; + if(privs & PRIV_SERVER) + os<<"server,"; if(privs & PRIV_SHOUT) os<<"shout,"; if(privs & PRIV_BAN) @@ -98,6 +102,8 @@ u64 stringToPrivs(std::string str) privs |= PRIV_SETTIME; else if(s == "privs") privs |= PRIV_PRIVS; + else if(s == "server") + privs |= PRIV_SERVER; else if(s == "shout") privs |= PRIV_SHOUT; else if(s == "ban") diff --git a/src/servercommand.cpp b/src/servercommand.cpp index c5b242b2e..48ada56fe 100644 --- a/src/servercommand.cpp +++ b/src/servercommand.cpp @@ -376,26 +376,7 @@ std::wstring processServerCommand(ServerCommandContext *ctx) std::wostringstream os(std::ios_base::binary); ctx->flags = SEND_TO_SENDER; // Default, unless we change it. - u64 privs = ctx->privs; - - if(ctx->parms.size() == 0 || ctx->parms[0] == L"help") - { - os<parms[0] == L"status") + if(ctx->parms[0] == L"status") cmd_status(os, ctx); else if(ctx->parms[0] == L"privs") cmd_privs(os, ctx);