/* $Id$
* EOSERV is released under the zlib license.
* See LICENSE.txt for more info.
*/
#include <algorithm>
#include "playercommands.hpp"
#include "../config.hpp"
#include "../console.hpp"
#include "../eoclient.hpp"
#include "../player.hpp"
#include "../world.hpp"
namespace PlayerCommands
{
void player_command_handler_register::Register(player_command_handler handler)
{
if (handler.info.partial_min_chars < 1)
handler.info.partial_min_chars = 1;
else if (handler.info.partial_min_chars > handler.info.name.length())
handler.info.partial_min_chars = handler.info.name.length();
auto result = handlers.insert(std::make_pair(handler.info.name, handler));
if (!result.second)
Console::Wrn("Duplicate command name: %s", handler.info.name.c_str());
}
void player_command_handler_register::RegisterAlias(const std::string& alias, const std::string& command)
{
auto result = aliases.insert(std::make_pair(alias, command));
if (!result.second)
Console::Wrn("Duplicate command alias name: %s", alias.c_str());
}
bool player_command_handler_register::Handle(std::string command, const std::vector<std::string>& arguments, Command_Source* from, int alias_depth) const
{
if (command.empty())
{
from->ServerMsg(from->SourceWorld()->i18n.Format("unknown_command"));
return false;
}
if (alias_depth > 100)
{
Console::Wrn("Command alias nested too deeply or infinitely recursive: %s", command.c_str());
return false;
}
auto player_command_result = handlers.find(command);
if (player_command_result != handlers.end() && player_command_result->second.info.arguments.size() <= arguments.size())
{
if (player_command_result->second.info.require_character && !from->SourceCharacter())
{
from->ServerMsg(from->SourceWorld()->i18n.Format("unknown_command"));
return false;
}
player_command_result->second.f(arguments, from);
return true;
}
else
{
auto alias_result = aliases.find(command);
if (alias_result != aliases.end())
{
return this->Handle(alias_result->second, arguments, from, alias_depth + 1);
}
auto match = handlers.end();
UTIL_CIFOREACH(handlers, handler)
{
if (command.length() < handler->second.info.partial_min_chars
|| command.length() >= handler->second.info.name.length())
continue;
std::string prefix = handler->second.info.name.substr(0, std::max(command.length(), handler->second.info.partial_min_chars));
if (command.substr(0, prefix.length()) == prefix)
{
if (handler->second.info.require_character && !from->SourceCharacter())
continue;
// Ambiguous abbreviation
if (match != handlers.end())
{
from->ServerMsg(from->SourceWorld()->i18n.Format("unknown_command"));
return false;
}
match = handler;
}
}
if (match != handlers.end())
{
if (match->second.info.arguments.size() > arguments.size())
{
from->ServerMsg(from->SourceWorld()->i18n.Format("command_not_enough_arguments"));
return false;
}
match->second.f(arguments, from);
return true;
}
}
from->ServerMsg(from->SourceWorld()->i18n.Format("unknown_command"));
return false;
}
player_command_handler_register *player_command_handler_register_instance;
void player_command_handler_register_init::init() const
{
player_command_handler_register_instance = new player_command_handler_register();
}
player_command_handler_register_init::~player_command_handler_register_init()
{
if (master)
delete player_command_handler_register_instance;
}
static player_command_handler_register_init player_command_handler_register_init_instance(true);
}