Skip to content

Commit

Permalink
Move privs command to core, fix issue minetest#12 by adding missing f…
Browse files Browse the repository at this point in the history
…inisher in command handlers
  • Loading branch information
nerzhul committed Aug 22, 2015
1 parent 7a244f2 commit 760916d
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 52 deletions.
17 changes: 0 additions & 17 deletions builtin/game/chatcommands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,6 @@ core.register_chatcommand("help", {
end
table.sort(cmds)
return true, "Available commands:\n"..table.concat(cmds, "\n")
elseif param == "privs" then
local privs = {}
for priv, def in pairs(core.registered_privileges) do
table.insert(privs, priv .. ": " .. def.description)
end
table.sort(privs)
return true, "Available privileges:\n"..table.concat(privs, "\n")
else
local cmd = param
local def = core.chatcommands[cmd]
Expand All @@ -105,16 +98,6 @@ core.register_chatcommand("help", {
end,
})

core.register_chatcommand("privs", {
params = "<name>",
description = "print out privileges of player",
func = function(name, param)
param = (param ~= "" and param or name)
return true, "Privileges of " .. param .. ": "
.. core.privs_to_string(
core.get_player_privs(param), ' ')
end,
})
core.register_chatcommand("grant", {
params = "<name> <privilege>|all",
description = "Give privilege to player",
Expand Down
4 changes: 2 additions & 2 deletions src/contrib/ban.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ bool ChatHandler::handleCommand_ban_player(std::string args, u16 peer_id)
}

std::vector<std::string> commandline;
std::stringstream ss(args.substr(1));
std::stringstream ss(args);
std::string item;
while (std::getline(ss, item, ' ')) {
commandline.push_back(item);
Expand Down Expand Up @@ -223,7 +223,7 @@ bool ChatHandler::handleCommand_unban_player(std::string args, u16 peer_id)
}

std::vector<std::string> commandline;
std::stringstream ss(args.substr(1));
std::stringstream ss(args);
std::string item;
while (std::getline(ss, item, ' ')) {
commandline.push_back(item);
Expand Down
113 changes: 81 additions & 32 deletions src/contrib/chathandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
**/

#include <string.h>
#include <sstream>
#include "log.h"
#include "server.h"
#include "contrib/chathandler.h"

namespace epixel
Expand All @@ -26,30 +29,45 @@ namespace epixel
ChatHandler::ChatHandler(Server *s): m_loaded(false), m_server(s)
{}

// @TODO: use gettext later
static const ChatCommand COMMANDHANDLERFINISHER = { NULL, NULL, NULL, L"" };
ChatCommand* ChatHandler::getCommandTable()
{
static ChatCommand banCommandTable[] =
{
{ "list", &ChatHandler::handleCommand_ban_list, NULL },
{ "player", &ChatHandler::handleCommand_ban_player, NULL },
{ "list", &ChatHandler::handleCommand_ban_list, NULL, L"" },
{ "player", &ChatHandler::handleCommand_ban_player, NULL, L"" },
COMMANDHANDLERFINISHER,
};

static ChatCommand areaCommandTable[] =
{
{ "list", &ChatHandler::handleCommand_area_list, NULL },
{ "remove", &ChatHandler::handleCommand_area_remove, NULL },
{ "list", &ChatHandler::handleCommand_area_list, NULL, L"" },
{ "remove", &ChatHandler::handleCommand_area_remove, NULL, L"" },
COMMANDHANDLERFINISHER,
};

static ChatCommand privCommandTable[] =
{
{ "grant", NULL, NULL, L"" }, // @TODO
{ "list", &ChatHandler::handleCommand_list_privs, NULL, L"" },
{ "revoke", NULL, NULL, L"" }, // @TODO
COMMANDHANDLERFINISHER,
};

static ChatCommand unbanCommandTable[] =
{
{ "player", &ChatHandler::handleCommand_unban_player, NULL },
{ "player", &ChatHandler::handleCommand_unban_player, NULL, L"" },
COMMANDHANDLERFINISHER,
};

static ChatCommand globalCommandTable[] =
{
{ "area", NULL, areaCommandTable },
{ "ban", NULL, banCommandTable },
{ "unban", NULL, unbanCommandTable },
{ "area", NULL, areaCommandTable, L"Sub commands available: list, remove." },
{ "ban", NULL, banCommandTable, L"Sub commands available: player." },
{ "privs", NULL, privCommandTable, L"Sub commands available: grant, list, revoke." },
{ "unban", NULL, unbanCommandTable, L"Sub commands available: player." },
COMMANDHANDLERFINISHER,
};

return globalCommandTable;
Expand All @@ -68,26 +86,33 @@ bool ChatHandler::handleCommand(const std::string &text, u16 peer_id)
// Remove the initial slash
const char* ctext = &(text.c_str())[1];

if (!findCommand(getCommandTable(), ctext, command, &parentCommand)) {
return false;
ChatCommandSearchResult res = findCommand(getCommandTable(), ctext, command, &parentCommand);
switch (res) {
case CHAT_COMMAND_OK:
(this->*(command->Handler))(ctext, peer_id);
return true;
case CHAT_COMMAND_UNKNOWN_SUBCOMMAND:
m_server->SendChatMessage(peer_id, command->help);
return true;
case CHAT_COMMAND_UNKNOWN:
default:
return false;
}

(this->*(command->Handler))(ctext, peer_id);
return true;
}

bool ChatHandler::findCommand(ChatCommand *table, const char* &text, ChatCommand*& command, ChatCommand** parentCommand)
ChatCommandSearchResult ChatHandler::findCommand(ChatCommand *table, const char* &text, ChatCommand*& command, ChatCommand** parentCommand)
{
std::string cmd;
std::string cmd = "";
// skip whitespaces
while (*text != ' ' && *text != '\0')
{
while (*text != ' ' && *text != '\0') {
cmd += *text;
++text;
}

while (*text == ' ') { ++text; }

actionstream << "Command: " << cmd << std::endl;

// search first level command in table
for (u32 i = 0; table[i].name != NULL; ++i) {
// If it's not the searched command, skip
Expand All @@ -100,21 +125,37 @@ bool ChatHandler::findCommand(ChatCommand *table, const char* &text, ChatCommand
if (table[i].childCommand != NULL) {
const char* stext = text;
ChatCommand* parentSubcommand = NULL;
ChatCommandSearchResult res = findCommand(table[i].childCommand, text, command, &parentSubcommand);

// Lookup child command
if (findCommand(table[i].childCommand, text, command, &parentSubcommand)) {
// if subcommand success search not return parent command, then
// this parent command is owner of child commands
if (parentCommand) {
*parentCommand = parentSubcommand ? parentSubcommand : &table[i];
}

// name == "" is special case: restore original command text
// for next level "" (where parentSubcommand==NULL)
if (strlen(command->name) == 0 && !parentSubcommand) {
text = stext;
}
return true;
switch (res) {
case CHAT_COMMAND_OK:
// if subcommand success search not return parent command, then
// this parent command is owner of child commands
if (parentCommand) {
*parentCommand = parentSubcommand ? parentSubcommand : &table[i];
}

// name == "" is special case: restore original command text
// for next level "" (where parentSubcommand==NULL)
if (strlen(command->name) == 0 && !parentSubcommand) {
text = stext;
}
return CHAT_COMMAND_OK;
case CHAT_COMMAND_UNKNOWN:
// command not found directly in child command list, return child command list owner
command = &table[i];
if (parentCommand)
*parentCommand = NULL; // we don't known parent of table list at this point

text = stext; // restore text to stated just after parse found parent command
return CHAT_COMMAND_UNKNOWN_SUBCOMMAND; // we not found subcommand for table[i]
case CHAT_COMMAND_UNKNOWN_SUBCOMMAND:
default:
// some deep subcommand not found, if this second level subcommand then parentCommand can be NULL, use known value for it
if (parentCommand)
*parentCommand = parentSubcommand ? parentSubcommand : &table[i];
return res;
}
}

Expand All @@ -130,9 +171,17 @@ bool ChatHandler::findCommand(ChatCommand *table, const char* &text, ChatCommand
*parentCommand = NULL;
}

return true;
return CHAT_COMMAND_OK;
}
return false;

// command not found in table directly
command = NULL;

// unknown table owner at this point
if (parentCommand)
*parentCommand = NULL;

return CHAT_COMMAND_UNKNOWN;
}

}
13 changes: 12 additions & 1 deletion src/contrib/chathandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ struct ChatCommand
const char* name;
bool (ChatHandler::*Handler)(std::string args, u16 peer_id);
ChatCommand* childCommand;
const std::wstring help;
};

enum ChatCommandSearchResult
{
CHAT_COMMAND_OK, // found accessible command by command string
CHAT_COMMAND_UNKNOWN, // first level command not found
CHAT_COMMAND_UNKNOWN_SUBCOMMAND, // command found but some level subcommand not find in subcommand list
};

class ChatHandler
Expand All @@ -53,8 +61,11 @@ class ChatHandler
bool handleCommand_ban_list(std::string args, u16 peer_id);
bool handleCommand_ban_player(std::string args, u16 peer_id);
bool handleCommand_unban_player(std::string args, u16 peer_id);

// Player privs
bool handleCommand_list_privs(std::string args, u16 peer_id);
private:
bool findCommand(ChatCommand* table, const char *&text, ChatCommand *&command, ChatCommand **parentCommand = NULL);
ChatCommandSearchResult findCommand(ChatCommand* table, const char *&text, ChatCommand *&command, ChatCommand **parentCommand = NULL);
ChatCommand* getCommandTable();

bool m_loaded;
Expand Down
40 changes: 40 additions & 0 deletions src/contrib/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
**/

#include "player.h"
#include "database.h"
#include "gamedef.h"
#include "server.h"
#include "content_sao.h"
#include "contrib/chathandler.h"

void Player::step(float dtime)
{
Expand Down Expand Up @@ -113,6 +115,44 @@ void Player::addExhaustion(float modifier)
getHuds()->getHudId(PLAYERHUD_HUNGER_FG), HUD_STAT_NUMBER, &hunger);
}
}
}

namespace epixel
{

bool ChatHandler::handleCommand_list_privs(std::string args, u16 peer_id)
{
std::vector<std::string> commandline;
std::stringstream ss(args);
std::string item;
while (std::getline(ss, item, ' ')) {
commandline.push_back(item);
}

if (commandline.size() > 1) {
m_server->SendChatMessage(peer_id, L"Invalid usage, see /help privs list");
return true;
}

std::string playername;
if (commandline.size() == 0) {
playername = m_server->getPlayerName(peer_id);
}
else {
playername = commandline[0];
}

std::set<std::string> privs;
m_server->getGameDatabase()->loadUserPrivs(playername, privs);

std::wstringstream ws;
ws << "Available privileges for " << playername.c_str() << ": ";
for (auto &priv: privs) {
ws << priv.c_str() << " ";
}
ws << std::endl;
m_server->SendChatMessage(peer_id, ws.str());
return true;
}

}
4 changes: 4 additions & 0 deletions src/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ class GameDatabase: public VirtualDatabase
std::set<std::string> privs;
return loadUser(login, pwdhash, privs, false);
}
inline bool loadUserPrivs(const std::string &login, std::set<std::string> &privs)
{
return loadUser(login, "", privs, true, true);
}

virtual bool removeUser(u32 id) = 0;
virtual u32 userExists(const std::string &login) = 0;
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
nrz::AreaMgr* getAreaMgr() { return m_area_mgr; }
nrz::BanMgr* getBanMgr() { return m_ban_mgr; }
nrz::CreatureStore* getCreatureStore() { return m_creaturestore; }
GameDatabase* getGameDatabase() { return m_game_database; }

private:

Expand Down

0 comments on commit 760916d

Please sign in to comment.