00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 ¶m1)
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 ¶m1,
00082 const Param ¶m2)
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 ¶m1,
00091 const Param ¶m2, const Param ¶m3)
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> ¶ms)
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 }