285 lines
6.6 KiB
C++
285 lines
6.6 KiB
C++
#include "Commands.h"
|
|
#include <boost/filesystem.hpp>
|
|
|
|
namespace Engine {
|
|
|
|
static Commands *CommandsInstance = NULL;
|
|
|
|
void trim_command_str (std::string &command_str) {
|
|
std::string::size_type start = command_str.find_first_not_of (" \t");
|
|
if (start != std::string::npos)
|
|
command_str = command_str.substr (start);
|
|
|
|
std::string::size_type end = command_str.find_first_of ("#;\n\r\0");
|
|
|
|
if (end != std::string::npos)
|
|
command_str = command_str.substr (0, end);
|
|
}
|
|
|
|
/*
|
|
* Inherited Module functions
|
|
*/
|
|
int Commands::OnInit (int argc, char* argv[]) {
|
|
LogDebug ("Commands Init");
|
|
mErrorString = "";
|
|
if (CommandsInstance) {
|
|
LogError ("Commands module already initialized!");
|
|
return -1;
|
|
}
|
|
|
|
CommandsInstance = this;
|
|
|
|
return 0;
|
|
}
|
|
void Commands::OnDestroy () {
|
|
LogDebug ("Commands Destroy");
|
|
|
|
if (CommandsInstance)
|
|
CommandsInstance = NULL;
|
|
}
|
|
|
|
/*
|
|
* Module specific functions
|
|
*/
|
|
std::string Commands::GetCommandName (const std::string &command) {
|
|
return command.substr (0, command.find_first_of (" ;\n\0"));
|
|
}
|
|
|
|
std::vector<std::string> Commands::ParseArgs (std::string &argument_str) {
|
|
std::vector<std::string> args;
|
|
std::string::size_type pos = argument_str.find_first_not_of (" ");
|
|
std::string::size_type next_token = 0;
|
|
|
|
while ( argument_str.length ()> pos && argument_str.find_first_of (" \"", pos) != std::string::npos) {
|
|
next_token = argument_str.find_first_of (" \"", pos);
|
|
|
|
if (next_token != std::string::npos && argument_str[next_token] =='"') {
|
|
pos = next_token;
|
|
next_token = argument_str.find_first_of ('"', pos + 1);
|
|
if (next_token != std::string::npos) {
|
|
args.push_back (argument_str.substr (pos + 1, next_token - pos - 1));
|
|
}
|
|
pos = argument_str.find_first_not_of (" ", next_token + 1);
|
|
|
|
} else {
|
|
args.push_back (argument_str.substr (pos, next_token - pos));
|
|
pos = argument_str.find_first_not_of (" ", next_token + 1);
|
|
}
|
|
}
|
|
|
|
if (pos != std::string::npos)
|
|
args.push_back (argument_str.substr (pos, argument_str.length ()));
|
|
|
|
return args;
|
|
}
|
|
|
|
void Commands::AddCommand (const std::string &name, command_cb callback){
|
|
LogDebug ("Adding Command '%s' at %x", name.c_str(), (void *) callback);
|
|
|
|
mCommandsCallbacks[name] = callback;
|
|
|
|
return;
|
|
}
|
|
|
|
bool Commands::RunCommand (const std::string &command){
|
|
LogDebug ("Running Command: %s", command.c_str());
|
|
|
|
std::string cmd_name = GetCommandName (command);
|
|
std::string args;
|
|
|
|
if (command.length () > cmd_name.length () + 1)
|
|
args = command.substr (cmd_name.length () + 1, command.length ());
|
|
|
|
if (mCommandsCallbacks.find (cmd_name) != mCommandsCallbacks.end()) {
|
|
std::vector<std::string> argv = ParseArgs (args);
|
|
if (mCommandsCallbacks[cmd_name] (argv)) {
|
|
mErrorString = "";
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
LogWarning ("Command '%s' not registered!", cmd_name.c_str ());
|
|
}
|
|
|
|
SetErrorString ("Command '" + cmd_name + "' does not exist!");
|
|
return false;
|
|
}
|
|
|
|
void Commands::QueueCommand (const std::string &command){
|
|
mCommandQueue.push (command);
|
|
}
|
|
|
|
bool Commands::QueueExecute (){
|
|
bool result = true;
|
|
|
|
while (mCommandQueue.size() > 0) {
|
|
result = RunCommand (mCommandQueue.front());
|
|
if (!result) {
|
|
while (!mCommandQueue.empty())
|
|
mCommandQueue.pop();
|
|
|
|
return false;
|
|
}
|
|
mCommandQueue.pop();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Commands::SetErrorString (const std::string &error_str){
|
|
mErrorString = error_str;
|
|
LogWarning ("Command Error: %s", error_str.c_str ());
|
|
}
|
|
|
|
std::string Commands::GetErrorString (){
|
|
return mErrorString;
|
|
}
|
|
|
|
|
|
/*
|
|
* Global functions
|
|
*/
|
|
bool CommandsInitialized () {
|
|
if (!CommandsInstance) {
|
|
LogError ("Commands System not yet initialized!");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AddCommand (const std::string &name, command_cb callback){
|
|
if (!CommandsInitialized ())
|
|
return;
|
|
|
|
CommandsInstance->AddCommand (name, callback);
|
|
}
|
|
|
|
bool RunCommand (const std::string &command){
|
|
if (!CommandsInitialized ())
|
|
return false;
|
|
|
|
return CommandsInstance->RunCommand (command);
|
|
}
|
|
|
|
void QueueCommand (const std::string &command){
|
|
if (!CommandsInitialized ())
|
|
return;
|
|
|
|
CommandsInstance->QueueCommand (command);
|
|
}
|
|
|
|
bool CommandQueueExecute (){
|
|
if (!CommandsInitialized ())
|
|
return false;
|
|
|
|
return CommandsInstance->QueueExecute ();
|
|
}
|
|
|
|
void CommandSetErrorString (const std::string &error_str){
|
|
if (!CommandsInitialized ())
|
|
return;
|
|
|
|
CommandsInstance->SetErrorString (error_str);
|
|
}
|
|
|
|
std::string CommandGetErrorString (){
|
|
if (!CommandsInitialized ())
|
|
return std::string("");
|
|
|
|
return CommandsInstance->GetErrorString();
|
|
}
|
|
|
|
/** \brief Searches for possible candidates at reasonable places
|
|
*
|
|
* In that order:
|
|
* 1. current directory
|
|
* 2. user data directory
|
|
* 3. game data directory
|
|
*
|
|
* \returns full path to the file, otherwise only the filename (which will
|
|
* \returns then cause an error because the file cannot be opened)
|
|
*/
|
|
std::string find_exec_file_full_path (const std::string &exec_file) {
|
|
std::string full_path = exec_file;
|
|
|
|
boost::filesystem::path exec_file_path (full_path);
|
|
if(boost::filesystem::is_regular_file(exec_file_path)) {
|
|
return full_path;
|
|
}
|
|
|
|
full_path = GetUserDirFullPath(std::string("/") + exec_file);
|
|
exec_file_path = full_path;
|
|
if(boost::filesystem::is_regular_file(exec_file_path)) {
|
|
return full_path;
|
|
}
|
|
|
|
full_path = GetResourceFullPath(std::string("/") + exec_file);
|
|
exec_file_path = full_path;
|
|
if(boost::filesystem::is_regular_file(exec_file_path)) {
|
|
return full_path;
|
|
}
|
|
|
|
// otherwise just return the normal path which will fail anyway
|
|
return exec_file;
|
|
}
|
|
|
|
/*
|
|
* Commands of the Command system
|
|
*/
|
|
bool Cmd_Exec (const std::vector<std::string> args) {
|
|
if (!CommandsInitialized())
|
|
return false;
|
|
|
|
if (args.size() != 1) {
|
|
CommandsInstance->SetErrorString("usage: exec <path_to_file>");
|
|
return false;
|
|
}
|
|
|
|
std::string full_path = find_exec_file_full_path(args[0]);
|
|
LogDebug ("Trying to exec file %s", full_path.c_str());
|
|
|
|
std::ifstream exec_file;
|
|
exec_file.open(full_path.c_str(), std::ios_base::in);
|
|
|
|
if (!exec_file) {
|
|
std::ostringstream error_msg;
|
|
error_msg << "exec failed: could not open file '"
|
|
<< full_path.c_str() << "'";
|
|
CommandsInstance->SetErrorString(error_msg.str());
|
|
return false;
|
|
}
|
|
|
|
int linecounter = 0;
|
|
while (!exec_file.eof()) {
|
|
std::string line;
|
|
getline (exec_file, line);
|
|
linecounter++;
|
|
|
|
trim_command_str (line);
|
|
|
|
if (line.size() == 0)
|
|
continue;
|
|
|
|
if (!CommandsInstance->RunCommand (line)) {
|
|
std::ostringstream error_msg;
|
|
error_msg << "exec failed running command '" << line
|
|
<< "' in file " << args[0] << ":" << linecounter << ".";
|
|
CommandsInstance->SetErrorString (error_msg.str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
exec_file.close();
|
|
LogDebug ("exec success for file %s", full_path.c_str());
|
|
return true;
|
|
}
|
|
|
|
void Commands::OnRegisterCommands () {
|
|
AddCommand ("exec", Cmd_Exec);
|
|
}
|
|
|
|
}
|
|
|