i6engine  1.0
LuaScriptingManager.h
Go to the documentation of this file.
1 /*
2  * i6engine
3  * Copyright (2016) Daniel Bonrath, Michael Baer, All rights reserved.
4  *
5  * This file is part of i6engine; i6engine is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
25 #ifndef __I6ENGINE_MODULES_LUASCRIPTINGMANAGER_H__
26 #define __I6ENGINE_MODULES_LUASCRIPTINGMANAGER_H__
27 
28 #include <map>
29 #include <set>
30 
33 #include "i6engine/utils/Future.h"
35 
37 
38 #include "i6engine/luabind/luabind.hpp"
39 
40 namespace i6e {
41 namespace api {
42  class ScriptingFacade;
43 } /* namespace api */
44 namespace modules {
45 
46  class LuaScriptingMailbox;
47 
49  friend class LuaScriptingMailbox;
50  friend class api::ScriptingFacade;
51 
52  public:
57 
62 
63  void Tick();
64 
68  template<typename Ret, typename... args>
69  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callScript(const std::string & file, const std::string & func, args... B) {
70  _callScripts.push(std::bind([this, file, func](args... A) {
71  ASSERT_THREAD_SAFETY_FUNCTION
72  if (!parseScript(file, false)) {
73  return;
74  }
75  try {
76  lua_getglobal(_luaState, func.c_str());
77  assert(lua_isfunction(_luaState, -1));
78  luabind::object o(luabind::from_stack(_luaState, -1));
79  luabind::call_function<Ret>(o, A...);
80  } catch (const luabind::error & e) {
81  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
82  } catch (const std::exception & e) {
83  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
84  }
85  }, B...));
86  }
87 
91  template<typename Ret, typename... args>
92  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callScript(const std::string & file, const std::string & func, args... B) {
93  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
94  _callScripts.push(std::bind([this, file, func, ret](args... A) {
95  ASSERT_THREAD_SAFETY_FUNCTION
96  if (!parseScript(file, false)) {
97  ret->push(Ret());
98  }
99  try {
100  lua_getglobal(_luaState, func.c_str());
101  assert(lua_isfunction(_luaState, -1));
102  luabind::object o(luabind::from_stack(_luaState, -1));
103  ret->push(Ret(luabind::call_function<Ret>(o, A...)));
104  } catch (const luabind::error & e) {
105  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
106  } catch (const std::exception & e) {
107  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
108  }
109  }, B...));
110  return ret;
111  }
112 
116  template<typename Ret, typename... args>
117  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callFunction(const std::string & func, args... B) {
118  _callScripts.push(std::bind([this, func](args... A) {
119  ASSERT_THREAD_SAFETY_FUNCTION
120  try {
121  lua_getglobal(_luaState, func.c_str());
122  assert(lua_isfunction(_luaState, -1));
123  luabind::object o(luabind::from_stack(_luaState, -1));
124  luabind::call_function<Ret>(o, A...);
125  } catch (const luabind::error & e) {
126  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
127  } catch (const std::exception & e) {
128  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
129  }
130  }, B...));
131  }
132 
136  template<typename Ret, typename... args>
137  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callFunction(const std::string & func, args... B) {
138  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
139  _callScripts.push(std::bind([this, func, ret](args... A) {
140  ASSERT_THREAD_SAFETY_FUNCTION
141  try {
142  lua_getglobal(_luaState, func.c_str());
143  assert(lua_isfunction(_luaState, -1));
144  luabind::object o(luabind::from_stack(_luaState, -1));
145  ret->push(Ret(luabind::call_function<Ret>(o, A...)));
146  } catch (const luabind::error & e) {
147  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
148  } catch (const std::exception & e) {
149  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
150  }
151  }, B...));
152  return ret;
153  }
154 
158  template<typename Ret, typename... args>
159  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callScriptWithCallback(const std::string & file, const std::string & func, const std::function<void(void)> & callback, args... B) {
160  _callScripts.push(std::bind([this, file, func, callback](args... A) {
161  ASSERT_THREAD_SAFETY_FUNCTION
162  if (!parseScript(file, false)) {
163  return;
164  }
165  try {
166  lua_getglobal(_luaState, func.c_str());
167  assert(lua_isfunction(_luaState, -1));
168  luabind::object o(luabind::from_stack(_luaState, -1));
169  luabind::call_function<Ret>(o, A...);
170  } catch (const luabind::error & e) {
171  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
172  } catch (const std::exception & e) {
173  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
174  }
175  callback();
176  }, B...));
177  }
178 
182  template<typename Ret, typename... args>
183  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callScriptWithCallback(const std::string & file, const std::string & func, const std::function<void(void)> & callback, args... B) {
184  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
185  _callScripts.push(std::bind([this, file, func, callback, ret](args... A) {
186  ASSERT_THREAD_SAFETY_FUNCTION
187  if (!parseScript(file, false)) {
188  ret->push(Ret());
189  }
190  try {
191  lua_getglobal(_luaState, func.c_str());
192  assert(lua_isfunction(_luaState, -1));
193  luabind::object o(luabind::from_stack(_luaState, -1));
194  ret->push(Ret(luabind::call_function<Ret>(o, A...)));
195  } catch (const luabind::error & e) {
196  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
197  } catch (const std::exception & e) {
198  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "' in script '" << file << ".lua': " << e.what() << ": " << lua_tostring(_luaState, -1));
199  }
200  callback();
201  }, B...));
202  return ret;
203  }
204 
208  template<typename Ret, typename... args>
209  typename std::enable_if<std::is_void<Ret>::value, Ret>::type callFunctionWithCallback(const std::string & func, const std::function<void(void)> & callback, args... B) {
210  _callScripts.push(std::bind([this, func, callback](args... A) {
211  ASSERT_THREAD_SAFETY_FUNCTION
212  try {
213  lua_getglobal(_luaState, func.c_str());
214  assert(lua_isfunction(_luaState, -1));
215  luabind::object o(luabind::from_stack(_luaState, -1));
216  luabind::call_function<Ret>(o, A...);
217  } catch (const luabind::error & e) {
218  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
219  } catch (const std::exception & e) {
220  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
221  }
222  callback();
223  }, B...));
224  }
225 
229  template<typename Ret, typename... args>
230  typename std::enable_if<!std::is_void<Ret>::value, std::shared_ptr<utils::Future<Ret>>>::type callFunctionWithCallback(const std::string & func, const std::function<void(void)> & callback, args... B) {
231  std::shared_ptr<utils::Future<Ret>> ret = std::make_shared<utils::Future<Ret>>();
232  _callScripts.push(std::bind([this, func, callback, ret](args... A) {
233  ASSERT_THREAD_SAFETY_FUNCTION
234  try {
235  lua_getglobal(_luaState, func.c_str());
236  assert(lua_isfunction(_luaState, -1));
237  luabind::object o(luabind::from_stack(_luaState, -1));
238  ret->push(Ret(luabind::call_function<Ret>(o, A...)));
239  } catch (const luabind::error & e) {
240  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
241  } catch (const std::exception & e) {
242  ISIXE_THROW_FAILURE("LuaScriptingManager", "Error calling function '" << func << "': " << e.what() << ": " << lua_tostring(_luaState, -1));
243  }
244  callback();
245  }, B...));
246  return ret;
247  }
248 
252  template<typename T>
253  typename std::enable_if<std::is_pointer<T>::value>::type setGlobalVariable(const std::string & name, T value) {
254  _callScripts.push(std::bind([this, name, value]() {
256  luabind::globals(_luaState)[name] = value;
257  }));
258  }
259 
263  void loadAllScripts();
264 
265  private:
266  lua_State * _luaState;
267  std::set<std::string> _parsedFiles;
268  std::string _scriptsPath;
269  utils::DoubleBufferQueue<std::function<void(void)>, true, false> _callScripts;
270 
274  void News(const api::GameMessage::Ptr & msg);
275 
279  bool parseScript(const std::string & file, bool completePath);
280 
284  LuaScriptingManager(const LuaScriptingManager &) = delete;
285 
289  LuaScriptingManager & operator=(const LuaScriptingManager &) = delete;
290 
292  };
293 
294 } /* namespace modules */
295 } /* namespace i6e */
296 
297 #endif /* __I6ENGINE_MODULES_LUASCRIPTINGMANAGER_H__ */
298 
Handles the incoming messages on the scripting channel and calls the corresponding methods...
#define ASSERT_THREAD_SAFETY_FUNCTION
#define ISIXE_MODULES_API
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callFunctionWithCallback(const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method with return type non-void and calls callback after scripts was executed ...
boost::shared_ptr< Message > Ptr
Definition: Message.h:66
std::enable_if< std::is_pointer< T >::value >::type setGlobalVariable(const std::string &name, T value)
sets a global variable
std::enable_if< std::is_void< Ret >::value, Ret >::type callScript(const std::string &file, const std::string &func, args...B)
executes the given method in the given script with return type void
std::enable_if< std::is_void< Ret >::value, Ret >::type callFunctionWithCallback(const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method with return type void and calls callback after scripts was executed ...
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callFunction(const std::string &func, args...B)
executes the given method with return type non-void
std::enable_if< std::is_void< Ret >::value, Ret >::type callScriptWithCallback(const std::string &file, const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method in the given script with return type void and calls callback after scripts ...
#define ASSERT_THREAD_SAFETY_HEADER
std::enable_if< std::is_void< Ret >::value, Ret >::type callFunction(const std::string &func, args...B)
executes the given method with return type void
#define ISIXE_THROW_FAILURE(module, message)
Definition: Exceptions.h:39
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callScript(const std::string &file, const std::string &func, args...B)
executes the given method in the given script with return type non-void
std::enable_if<!std::is_void< Ret >::value, std::shared_ptr< utils::Future< Ret > > >::type callScriptWithCallback(const std::string &file, const std::string &func, const std::function< void(void)> &callback, args...B)
executes the given method in the given script with return type non-void and calls callback after scri...