You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/apps/openmw-mp/Script/CommandController.cpp

104 lines
3.3 KiB
C++

//
// Created by koncord on 08.08.17.
//
#include "CommandController.hpp"
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <components/misc/stringops.hpp>
#include "Player.hpp"
#include "LuaState.hpp"
using namespace std;
void CommandController::Init(LuaState &lua)
{
sol::table cmdCtrlTable = lua.getState()->create_named_table("CommandController");
cmdCtrlTable["registerCommand"] = [&lua](const std::string &command, sol::function func, const std::string &helpMessage) {
return lua.getCmdCtrl().registerCommand(Misc::StringUtils::lowerCase(command), func, helpMessage);
};
cmdCtrlTable["unregisterCommand"] = [&lua](const std::string &command) {
lua.getCmdCtrl().unregisterCommand(Misc::StringUtils::lowerCase(command));
};
cmdCtrlTable["hasCommand"] = [&lua](const std::string &command) {
return lua.getCmdCtrl().hasCommand(Misc::StringUtils::lowerCase(command));
};
cmdCtrlTable["getHelpStrings"] = [&lua]() {
auto &commands = lua.getCmdCtrl().commands;
sol::table helpTable = lua.getState()->create_table(commands.size(), 0);
for (const auto &cmd : commands)
helpTable.add(cmd.first, cmd.second.helpMessage);
return helpTable;
};
}
bool CommandController::registerCommand(const std::string &command, sol::function func, const std::string &helpMessage)
{
auto iter = commands.find(command);
if (iter == commands.end())
{
commands.emplace(command, Command {std::move(func), helpMessage});
return true;
}
return false;
}
void CommandController::unregisterCommand(const std::string &command)
{
commands.erase(command);
}
bool CommandController::hasCommand(const std::string &command)
{
return commands.find(command) != commands.end();
}
std::pair<CommandController::ExecResult, std::string> CommandController::exec(const std::shared_ptr<Player> &player,
const std::string &message, unsigned channel)
{
char cmdChar = message[0];
if (message.size() < 2 || (cmdChar != '/' && cmdChar != '!'))
return make_pair(ExecResult::NOT_CMD, "");
auto tokens = cmdParser(message);
auto cmd = commands.find(Misc::StringUtils::lowerCase(&tokens[0][1]));
if (cmd != commands.end())
{
tokens.pop_front();
bool result = cmd->second.func(player, sol::as_table(move(tokens)), channel);
if (result)
return make_pair(ExecResult::SUCCESS, "");
return make_pair(ExecResult::FAIL, cmd->second.helpMessage);
}
return make_pair(ExecResult::NOT_FOUND, "");
}
std::deque<std::string> CommandController::cmdParser(const std::string &message)
{
deque<string> ret;
namespace x3 = boost::spirit::x3;
auto const sep = ' ';
auto const quoted = '"' >> *~x3::char_('"') >> '"';
auto const unquoted = *~x3::char_(sep);
auto const arguments = (quoted | unquoted) % sep;
/*auto const command = '/' >> *~x3::char_(sep) >> sep;
if (!x3::phrase_parse(message.cbegin(), message.cend(), arguments, command, ret))
Utils::throwError("failed to parse message: "+ message);*/
if (!x3::parse(message.cbegin(), message.cend(), arguments, ret))
Utils::throwError("failed to parse message: " + message);
return ret;
}