LUAScriptHook.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <lua/LUAScriptHook.h>
00022 #include <XML/XMLFile.h>
00023 #include <common/FileList.h>
00024 #include <common/Logger.h>
00025 #ifndef S3D_SERVER
00026 #include <console/ConsoleRuleMethodIAdapter.h>
00027 #endif
00028 
00029 LUAScriptHook::LUAScriptHook(LUAScriptFactory *factory, 
00030         const std::string &hooksName,
00031         const std::string &directoryName) :
00032         factory_(factory),
00033         hooksName_(hooksName),
00034         directoryName_(directoryName)
00035 {
00036 #ifndef S3D_SERVER
00037 
00038         new ConsoleRuleMethodIAdapter<LUAScriptHook>(
00039                 this, &LUAScriptHook::clearHooks, "scriptHook", 
00040                 ConsoleUtil::formParams(
00041                         ConsoleRuleParam(hooksName_),
00042                         ConsoleRuleParam("clear")));
00043         new ConsoleRuleMethodIAdapter<LUAScriptHook>(
00044                 this, &LUAScriptHook::reloadHooks, "scriptHook", 
00045                 ConsoleUtil::formParams(
00046                         ConsoleRuleParam(hooksName_),
00047                         ConsoleRuleParam("load")));
00048         new ConsoleRuleMethodIAdapter<LUAScriptHook>(
00049                 this, &LUAScriptHook::listHooks, "scriptHook", 
00050                 ConsoleUtil::formParams(
00051                         ConsoleRuleParam(hooksName_),
00052                         ConsoleRuleParam("list")));
00053 
00054 #endif
00055 }
00056 
00057 LUAScriptHook::~LUAScriptHook()
00058 {
00059 }
00060 
00061 void LUAScriptHook::addHookProvider(const std::string &hookName)
00062 {
00063         hookNames_.insert(
00064                 std::pair<std::string, std::vector<HookEntry> >
00065                         (hookName, std::vector<HookEntry>()));
00066 }
00067 
00068 void LUAScriptHook::callHook(const std::string &hookName)
00069 {
00070         std::vector<Param> result;
00071         callHookInternal(hookName, result);     
00072 }
00073 
00074 void LUAScriptHook::callHook(const std::string &hookName, const Param &param1)
00075 {
00076         std::vector<Param> result;
00077         result.push_back(param1);
00078         callHookInternal(hookName, result);     
00079 }
00080 
00081 void LUAScriptHook::callHook(const std::string &hookName, const Param &param1, 
00082         const Param &param2)
00083 {
00084         std::vector<Param> result;
00085         result.push_back(param1);
00086         result.push_back(param2);
00087         callHookInternal(hookName, result);     
00088 }
00089 
00090 void LUAScriptHook::callHook(const std::string &hookName, const Param &param1, 
00091         const Param &param2, const Param &param3)
00092 {
00093         std::vector<Param> result;
00094         result.push_back(param1);
00095         result.push_back(param2);
00096         result.push_back(param3);
00097         callHookInternal(hookName, result);     
00098 }
00099 
00100 void LUAScriptHook::callHookInternal(const std::string &hookName, const std::vector<Param> &params)
00101 {
00102         std::map<std::string, std::vector<HookEntry> >::iterator hookItor =
00103                 hookNames_.find(hookName);
00104         if (hookItor == hookNames_.end()) return;
00105 
00106         std::vector<Param>::const_iterator paramItor;
00107         std::vector<Param>::const_iterator endParamItor = params.end();
00108         std::vector<HookEntry>::iterator 
00109                 itor = hookItor->second.begin(), 
00110                 endItor = hookItor->second.end();
00111         for (;itor != endItor;itor++)
00112         {
00113                 LUAScript *script = itor->script;
00114                 if (!script->startFunction(itor->entryPoint)) continue;
00115 
00116                 for (paramItor = params.begin();
00117                         paramItor != endParamItor;
00118                         paramItor++)
00119                 {
00120                         switch (paramItor->type) 
00121                         {
00122                         case Param::eNumber:
00123                                 script->addNumberParameter(paramItor->number);
00124                                 break;
00125                         case Param::eBoolean:
00126                                 script->addBoolParameter(paramItor->boolean);
00127                                 break;
00128                         default:
00129                                 script->addStringParameter(paramItor->str);
00130                                 break;
00131                         }
00132                 }
00133 
00134                 script->endFunction((int) params.size());
00135         }
00136 }
00137 
00138 void LUAScriptHook::listHooks()
00139 {
00140         Logger::log("Hooks -----------------------------");
00141         std::map<std::string, std::vector<HookEntry> >::iterator topItor;
00142         for (topItor = hookNames_.begin();
00143                 topItor != hookNames_.end();
00144                 topItor++)
00145         {
00146                 Logger::log(S3D::formatStringBuffer("  %s", topItor->first.c_str()));
00147         }
00148 }
00149 
00150 void LUAScriptHook::clearHooks()
00151 {
00152         std::map<std::string, std::vector<HookEntry> >::iterator topItor;
00153         for (topItor = hookNames_.begin();
00154                 topItor != hookNames_.end();
00155                 topItor++)
00156         {
00157                 std::vector<HookEntry>::iterator itor;
00158                 for (itor = topItor->second.begin();
00159                         itor != topItor->second.end();
00160                         itor++)
00161                 {
00162                         HookEntry &entry = *itor;
00163                         delete entry.script;
00164                 }
00165                 topItor->second.clear();
00166         }
00167 }
00168 
00169 bool LUAScriptHook::loadHooks()
00170 {
00171         clearHooks();
00172 
00173         FileList fileList(directoryName_, "*.xml", true);
00174 
00175         FileList::ListType &files = fileList.getFiles();
00176         FileList::ListType::iterator itor;
00177         for (itor = files.begin();
00178                 itor != files.end();
00179                 itor++)
00180         {
00181                 if (!loadHook(directoryName_, *itor)) return false;
00182         }
00183 
00184         return true;
00185 }
00186 
00187 bool LUAScriptHook::loadHook(const std::string &directoryName, const std::string &fileName)
00188 {
00189         XMLFile file;
00190     if (!file.readFile(fileName))
00191         {
00192                 S3D::dialogMessage("LUAScriptHook", S3D::formatStringBuffer(
00193                         "Failed to parse \"%s\"\n%s", 
00194                         fileName.c_str(),
00195                         file.getParserError()));
00196                 return false;
00197         }
00198         if (!file.getRootNode()) return true;
00199         
00200     std::list<XMLNode *>::iterator childrenItor;
00201         std::list<XMLNode *> &children = file.getRootNode()->getChildren();
00202     for (childrenItor = children.begin();
00203                  childrenItor != children.end();
00204                  childrenItor++)
00205     {
00206         XMLNode *currentNode = (*childrenItor);
00207 
00208                 std::string scriptFileName, error;
00209                 if (!currentNode->getNamedChild("filename", scriptFileName)) return false;
00210 
00211                 if (scriptFileName.length() > 0 &&
00212                         scriptFileName[0] != '/' &&
00213                         scriptFileName[0] != '\\')
00214                 {
00215                         scriptFileName = directoryName + "/" + scriptFileName;
00216                 }
00217 
00218                 LUAScript *script = factory_->createScript();
00219                 if (!script->loadFromFile(scriptFileName, error))
00220                 {
00221                         S3D::dialogMessage("LUAScriptHook", S3D::formatStringBuffer(
00222                                 "From file %s, failed to parse LUA script \"%s\"\n%s", 
00223                                 fileName.c_str(),
00224                                 scriptFileName.c_str(),
00225                                 error.c_str()));
00226                         return false;
00227                 }
00228 
00229                 XMLNode *hook = 0;
00230                 while (currentNode->getNamedChild("hook", hook, false))
00231                 {
00232                         std::string hookName, entryPoint;
00233                         if (!hook->getNamedChild("hookname", hookName)) return false;
00234                         if (!hook->getNamedChild("entrypoint", entryPoint)) return false;
00235 
00236                         std::map<std::string, std::vector<HookEntry> >::iterator hookItor =
00237                                 hookNames_.find(hookName);
00238                         if (hookItor == hookNames_.end())
00239                         {
00240                                 S3D::dialogMessage("LUAScriptHook", S3D::formatStringBuffer(
00241                                         "From file %s, failed to find hook %s for LUA script \"%s\"", 
00242                                         fileName.c_str(),
00243                                         hookName.c_str(),
00244                                         scriptFileName.c_str()));
00245                                 return false;
00246                         }
00247 
00248                         if (!script->functionExists(entryPoint))
00249                         {
00250                                 S3D::dialogMessage("LUAScriptHook", S3D::formatStringBuffer(
00251                                         "From file %s, failed to find entrypoint %s in LUA script \"%s\"", 
00252                                         fileName.c_str(),
00253                                         entryPoint.c_str(),
00254                                         scriptFileName.c_str()));
00255                                 return false;
00256                         }
00257 
00258                         HookEntry hookEntry = { script, entryPoint };
00259                         hookItor->second.push_back(hookEntry);
00260                 }
00261         }
00262 
00263         return true;
00264 }

Generated on Mon Feb 16 15:14:51 2009 for Scorched3D by  doxygen 1.5.3