Leviathan  0.8.0.0
Leviathan game engine
ScriptExecutor.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "ScriptExecutor.h"
3 
4 #include "AccessMask.h"
7 #include "ScriptModule.h"
8 #include "ScriptNotifiers.h"
9 
10 #include <add_on/datetime/datetime.h>
11 #include <add_on/scriptany/scriptany.h>
12 #include <add_on/scriptarray/scriptarray.h>
13 #include <add_on/scriptdictionary/scriptdictionary.h>
14 #include <add_on/scriptgrid/scriptgrid.h>
15 #include <add_on/scripthandle/scripthandle.h>
16 #include <add_on/scripthelper/scripthelper.h>
17 #include <add_on/scriptmath/scriptmath.h>
18 #include <add_on/scriptmath/scriptmathcomplex.h>
19 #include <add_on/scriptstdstring/scriptstdstring.h>
20 #include <add_on/weakref/weakref.h>
21 
22 // Bindings
24 
25 using namespace Leviathan;
26 // ------------------------------------ //
27 namespace Leviathan {
28 
29 void ScriptMessageCallback(const asSMessageInfo* msg, void* param)
30 {
31  if(msg->type == asMSGTYPE_WARNING) {
32 
33  Logger::Get()->Write(std::string("[SCRIPT] [WARNING] ") + msg->section + " (" +
34  std::to_string(msg->row) + ", " + std::to_string(msg->col) +
35  ") : " + msg->message);
36 
37  } else if(msg->type == asMSGTYPE_INFORMATION) {
38 
39  Logger::Get()->Write(std::string("[SCRIPT] [INFO] ") + msg->section + " (" +
40  std::to_string(msg->row) + ", " + std::to_string(msg->col) +
41  ") : " + msg->message);
42 
43  } else {
44 
45  Logger::Get()->Write(std::string("[SCRIPT] [ERROR] ") + msg->section + " (" +
46  std::to_string(msg->row) + ", " + std::to_string(msg->col) +
47  ") : " + msg->message);
48  }
49 }
50 
51 #ifdef ANGELSCRIPT_HAS_TRANSLATE_CALLBACK
52 void ScriptTranslateExceptionCallback(asIScriptContext* context, void* userdata)
53 {
54  try {
55  std::rethrow_exception(std::current_exception());
56 
57  } catch(const Leviathan::InvalidAccess& e) {
58  context->SetException(
59  (std::string("Caught Leviathan::InvalidAccess exception: ") + e.what()).c_str());
60  } catch(const Leviathan::InvalidArgument& e) {
61  context->SetException(
62  (std::string("Caught Leviathan::InvalidArgument exception: ") + e.what()).c_str());
63  } catch(const Leviathan::InvalidState& e) {
64  context->SetException(
65  (std::string("Caught Leviathan::InvalidState exception: ") + e.what()).c_str());
66  } catch(const Leviathan::InvalidType& e) {
67  context->SetException(
68  (std::string("Caught Leviathan::InvalidType exception: ") + e.what()).c_str());
69  } catch(const Leviathan::NotFound& e) {
70  context->SetException(
71  (std::string("Caught Leviathan::NotFound exception: ") + e.what()).c_str());
72  } catch(const Leviathan::NULLPtr& e) {
73  context->SetException(
74  (std::string("Caught Leviathan::NULLPtr exception: ") + e.what()).c_str());
75  } catch(const Leviathan::Exception& e) {
76  context->SetException(
77  (std::string("Caught Leviathan::Exception: ") + e.what()).c_str());
78 
79 
80 
81  // } catch(const Ogre::Exception& e) {
82  // context->SetException((std::string("Caught Ogre::Exception: ") +
83  // e.what()).c_str());
84  } catch(const std::exception& e) {
85  context->SetException(
86  (std::string("Caught (unknown type) application exception: ") + e.what()).c_str());
87  } catch(...) {
88  // Use default message
89  }
90 }
91 #endif // ANGELSCRIPT_HAS_TRANSLATE_CALLBACK
92 
93 asIScriptContext* RequestContextCallback(asIScriptEngine* engine, void* userdata)
94 {
95  return static_cast<ScriptExecutor*>(userdata)->_GetContextForExecution();
96 }
97 
98 void ReturnContextCallback(asIScriptEngine* engine, asIScriptContext* context, void* userdata)
99 {
100  static_cast<ScriptExecutor*>(userdata)->_DoneWithContext(context);
101 }
102 
103 } // namespace Leviathan
104 
105 ScriptExecutor::ScriptExecutor() : engine(nullptr), AllocatedScriptModules()
106 {
107  instance = this;
108 
109  // Initialize AngelScript //
110  engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
111  if(engine == nullptr) {
112 
113  Logger::Get()->Error("ScriptExecutor: Init: asCreateScriptEngine failed");
114  Logger::Get()->Info("ScriptExecutor: tried to init angelscript version " +
115  Convert::ToString(ANGELSCRIPT_VERSION));
116  Logger::Get()->Write("Did you use a wrong angelscript version when compiling?");
117  throw Exception("Failed to init angelscript");
118  }
119 
120  // set callback to error report function //
121  engine->SetMessageCallback(asFUNCTION(ScriptMessageCallback), 0, asCALL_CDECL);
122 
123  // The ScriptExecutor can be retrieved from asIScriptEngine user data
124  engine->SetUserData(this);
125 
126 #ifdef ANGELSCRIPT_HAS_TRANSLATE_CALLBACK
127  // Set error translation callback
128  engine->SetTranslateAppExceptionCallback(
129  asFUNCTION(ScriptTranslateExceptionCallback), nullptr, asCALL_CDECL);
130 #endif // ANGELSCRIPT_HAS_TRANSLATE_CALLBACK
131 
132  // Context pool usage callbacks
133  engine->SetContextCallbacks(RequestContextCallback, ReturnContextCallback, this);
134 
135 
136  // Builtins are in this access group //
137  const auto initialMask =
138  engine->SetDefaultAccessMask(static_cast<AccessFlags>(ScriptAccess::Builtin));
139 
140  // math functions //
141  RegisterScriptMath(engine);
142  RegisterScriptMathComplex(engine);
143 
144  // register script string type //
145  RegisterStdString(engine);
146  RegisterScriptArray(engine, true);
147  // register other script extensions //
148  RegisterStdStringUtils(engine);
149 
150 
151  RegisterScriptDateTime(engine);
152 
153  // register dictionary object //
154  RegisterScriptDictionary(engine);
155 
156  // Register the grid addon //
157  RegisterScriptGrid(engine);
158 
159  // Register reference handles //
160  RegisterScriptHandle(engine);
161 
162  RegisterScriptWeakRef(engine);
163 
164  RegisterScriptAny(engine);
165 
166  // Put the extended standard stuff also in Builtin access mask
167 
168  if(!BindStandardFunctions(engine))
169  throw Exception("BindStandardFunctions failed");
170 
171  // All normal engine stuff is in the DefaultEngine access mask //
172  engine->SetDefaultAccessMask(static_cast<AccessFlags>(ScriptAccess::DefaultEngine));
173 
174  if(!BindTypes(engine))
175  throw Exception("BindTypes failed");
176 
177  if(!BindPhysics(engine))
178  throw Exception("BindNewton failed");
179 
180  if(!BindEngineCommon(engine))
181  throw Exception("BindEngineCommon failed");
182 
183  if(!BindRendering(engine))
184  throw Exception("BindRendering failed");
185 
186  if(!BindGUI(engine))
187  throw Exception("BindGUI failed");
188 
189  if(!BindEntity(engine))
190  throw Exception("BindEntity failed");
191 
192  // Bind notifiers //
193  if(!RegisterNotifiersWithAngelScript(engine)) {
194  // failed //
195  LOG_ERROR("ScriptExecutor: Init: AngelScript: register Notifier types failed");
196  throw Exception("Script bind failed");
197  }
198 
199  // Restore the default mask to let the application do what it wants with the masks
200  engine->SetDefaultAccessMask(initialMask);
201 
202  // bind application specific //
203  auto leviathanengine = Engine::GetEngine();
204 
205  if(leviathanengine) {
206 
207  if(!leviathanengine->GetOwningApplication()->InitLoadCustomScriptTypes(engine)) {
208 
209  LOG_ERROR("ScriptExecutor: Init: AngelScript: application register failed");
210  throw Exception("Script bind failed");
211  }
212  }
213 
214  // Verify void type //
215  const auto actualVoid = engine->GetTypeIdByDecl("void");
216  if(actualVoid != ANGELSCRIPT_VOID_TYPEID) {
217 
218  LOG_FATAL("ScriptExecutor: angelscript void type has changed! expected " +
219  std::to_string(ANGELSCRIPT_VOID_TYPEID) +
220  " (constexpr) == " + std::to_string(actualVoid) + " (actual value)");
221  }
222 }
224 {
225  {
226  Lock lock(ModulesLock);
227  auto end = AllocatedScriptModules.end();
228  for(auto iter = AllocatedScriptModules.begin(); iter != end; ++iter) {
229 
230  (*iter)->Release();
231  }
232 
233  // release/delete all modules //
234  AllocatedScriptModules.clear();
235  }
236 
237  // Release all context objects
238  for(asIScriptContext* context : ContextPool) {
239  context->Release();
240  }
241 
242  ContextPool.clear();
243 
244  // release AngelScript //
245  if(engine) {
246 
247  engine->Release();
248  engine = nullptr;
249  }
250 
251  instance = nullptr;
252 }
253 
255 {
256  return instance;
257 }
258 
259 ScriptExecutor* Leviathan::ScriptExecutor::instance = nullptr;
260 // ------------------------------------ //
262  ScriptModule* module, ScriptRunningSetup& parameters)
263 {
264  if(!module) {
265 
266  if(parameters.PrintErrors) {
267  Logger::Get()->Error("ScriptExecutor: GetFunctionFromModule: module is nullptr");
268  }
269 
270  return nullptr;
271  }
272 
273  asIScriptFunction* func;
274 
275  asIScriptModule* asModule = module->GetModule();
276 
277  if(!asModule) {
278 
279  if(parameters.PrintErrors) {
280  Logger::Get()->Error(
281  "ScriptExecutor: GetFunctionFromModule: cannot get function from "
282  "an invalid script module: " +
283  module->GetInfoString());
284  }
285 
286  return nullptr;
287  }
288 
289  // Get the entry function from the module //
290  if(!parameters.FullDeclaration) {
291 
292  func = asModule->GetFunctionByName(parameters.Entryfunction.c_str());
293 
294  } else {
295 
296  func = asModule->GetFunctionByDecl(parameters.Entryfunction.c_str());
297  }
298 
299  if(!_CheckScriptFunctionPtr(func, parameters, module)) {
300 
301  return nullptr;
302  }
303 
304  return func;
305 }
306 // ------------------------------------ //
308 {
309  asITypeInfo* info = engine->GetTypeInfoById(objid);
310 
311  asUINT count = info->GetBehaviourCount();
312 
313  for(asUINT i = 0; i < count; ++i) {
314 
315  asEBehaviours behaviour;
316  asIScriptFunction* func = info->GetBehaviourByIndex(i, &behaviour);
317 
318  if(!func) {
319 
320  LOG_ERROR("ScriptExecutor: RunReleaseRefOnObject: failed to get behaviour");
321  continue;
322  }
323 
324  if(behaviour == asBEHAVE_RELEASE) {
325 
326  LOG_INFO(
327  "ScriptExecutor: RunReleaseRefOnObject: Found asBEHAVE_RELEASE, calling it");
328 
329  ScriptRunningSetup ssetup;
330  const auto result = RunScriptMethod<void>(ssetup, func, obj);
331 
332  if(result.Result != SCRIPT_RUN_RESULT::Success)
333  throw Exception("Failed to run release behaviour");
334 
335  return;
336  }
337  }
338 
339  throw Exception("Didn't find release ref behaviour on object type");
340 }
341 // ------------------------------------ //
342 DLLEXPORT std::unique_ptr<CustomScriptRun> ScriptExecutor::PrepareCustomScriptRun(
343  asIScriptFunction* func, ScriptRunningSetup extraoptions /*= ScriptRunningSetup()*/)
344 {
345  if(!func)
346  return nullptr;
347 
348  auto run = std::make_unique<CustomScriptRun>(this);
349  run->Setup = extraoptions;
350  run->Func = func;
351 
352  // // TODO: this is a performance waste if there are no errors
353  // std::shared_ptr<ScriptModule> module =
354  // GetScriptModuleByFunction(func, run->Setup.PrintErrors);
355 
356  // Create a running context for the function //
357  run->Context = _GetContextForExecution();
358 
359  if(!run->Context) {
360  // Should this be fatal?
361  LOG_ERROR("ScriptExecutor: PrepareCustomScriptRun: failed to create a new context");
362  return nullptr;
363  }
364 
365  if(!_PrepareContextForPassingParameters(
366  func, run->Context, run->Setup, run->Module.get())) {
367 
368  _DoneWithContext(run->Context);
369  return nullptr;
370  }
371 
372  return run;
373 }
374 // ------------------------------------ //
376  asIScriptFunction* func, bool reporterror)
377 {
378  const char* nameStr = func->GetModuleName();
379 
380  if(!nameStr || strlen(nameStr) <= 1)
381  return nullptr;
382 
383  // static_cast<ScriptModule*>(func->GetModule()->GetUserData());
384  // then find by pointer in valid script modules
385 
386  std::shared_ptr<ScriptModule> module =
387  GetModuleByAngelScriptName(func->GetModuleName()).lock();
388 
389  if(!module) {
390 
391  if(reporterror) {
392  LOG_WARNING("ScriptExecutor: GetScriptModuleByFunction: the module is no longer "
393  "available: " +
394  std::string(func->GetModuleName()));
395  }
396  }
397 
398  return module;
399 }
400 // ------------------------------------ //
401 DLLEXPORT bool Leviathan::ScriptExecutor::_CheckScriptFunctionPtr(
402  asIScriptFunction* func, ScriptRunningSetup& parameters, ScriptModule* scriptmodule)
403 {
404  // Check is it null //
405  if(func == nullptr) {
406  // Set exists state //
407  parameters.ScriptExisted = false;
408 
409  // Check should we print an error //
410  if(parameters.PrintErrors && parameters.ErrorOnNonExistingFunction) {
411 
412  LOG_ERROR(
413  "ScriptExecutor: RunScript: Could not find starting function: " +
414  parameters.Entryfunction +
415  (scriptmodule ? (" in: " + scriptmodule->GetInfoString()) : std::string()));
416 
417  if(scriptmodule)
418  scriptmodule->PrintFunctionsInModule();
419  }
420 
421  // Not valid //
422  return false;
423  }
424 
425  // Set exists state //
426  parameters.ScriptExisted = true;
427 
428  return true;
429 }
430 
431 DLLEXPORT bool Leviathan::ScriptExecutor::_PrepareContextForPassingParameters(
432  asIScriptFunction* func, asIScriptContext* ScriptContext, ScriptRunningSetup& parameters,
433  ScriptModule* scriptmodule)
434 {
435  if(ScriptContext->Prepare(func) < 0) {
436 
437  Logger::Get()->Error(
438  "ScriptExecutor: RunScript: prepare context failed, func: " +
439  parameters.Entryfunction +
440  (scriptmodule ? (" in: " + scriptmodule->GetInfoString()) : std::string()));
441 
442  return false;
443  }
444 
445  return true;
446 }
447 
448 // ------------------------------------ //
450 {
451  // TODO: check for recursive call
452 
453  Lock guard(ContextPoolLock);
454 
455  // Get from pool if possible
456  if(!ContextPool.empty()) {
457  auto* ptr = ContextPool.back();
458  ContextPool.pop_back();
459  return ptr;
460  }
461 
462  // Needs more contexts
463  asIScriptContext* scriptContext = engine->CreateContext();
464 
465  if(!scriptContext) {
466 
467  LOG_ERROR("ScriptExecutor: _GetContextForExecution: Failed to create a new context");
468  return nullptr;
469  }
470 
471  return scriptContext;
472 }
473 
475 {
476  Lock guard(ContextPoolLock);
477 
478  // Only keep 1000 contexts at most
479  if(ContextPool.size() < 1000) {
480 
481  ContextPool.push_back(context);
482  context->Unprepare();
483 
484  } else {
485 
486  context->Release();
487  }
488 }
489 // ------------------------------------ //
490 DLLEXPORT std::weak_ptr<ScriptModule> Leviathan::ScriptExecutor::GetModule(const int& ID)
491 {
492  // loop modules and return a ptr to matching id //
493  Lock lock(ModulesLock);
494 
495  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
496  if(AllocatedScriptModules[i]->GetID() == ID)
497  return AllocatedScriptModules[i];
498  }
499 
500  return std::shared_ptr<ScriptModule>(nullptr);
501 }
502 
504  const char* nameofmodule)
505 {
506  // Find a matching name //
507  std::string module(nameofmodule);
508 
509  Lock lock(ModulesLock);
510 
511  // TODO: check could this be checked by comparing pointers
512  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
513  if(AllocatedScriptModules[i]->GetModuleName() == module)
514  return AllocatedScriptModules[i];
515  }
516 
517  return std::shared_ptr<ScriptModule>(nullptr);
518 }
519 // ------------------------------------ //
521  const std::string& name, const std::string& source, const int& modulesid
522  /*= IDFactory::GetID()*/)
523 {
524  // create new module to a smart pointer //
525  auto tmpptr = std::make_shared<ScriptModule>(engine, name, modulesid, source);
526 
527  // add to vector and return //
528  Lock lock(ModulesLock);
529  AllocatedScriptModules.push_back(tmpptr);
530  return tmpptr;
531 }
532 
534 {
535 
536  Lock lock(ModulesLock);
537 
538  // find module based on pointer and remove //
539  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
540  if(AllocatedScriptModules[i].get() == ptrtomatch) {
541 
542  AllocatedScriptModules[i]->Release();
543  // remove //
544  AllocatedScriptModules.erase(AllocatedScriptModules.begin() + i);
545  return;
546  }
547  }
548 }
549 
551 {
552 
553  Lock lock(ModulesLock);
554 
555  // Find based on the id //
556  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
557  if(AllocatedScriptModules[i]->GetID() == ID) {
558  // Check reference count //
559  if(AllocatedScriptModules[i].use_count() != 1) {
560  // Other references exist //
561  return false;
562  }
563 
564  AllocatedScriptModules[i]->Release();
565 
566  // remove //
567  AllocatedScriptModules.erase(AllocatedScriptModules.begin() + i);
568  return true;
569  }
570  }
571  // Nothing found //
572  return false;
573 }
574 // ------------------------------------ //
575 DLLEXPORT bool ScriptExecutor::_DoPassParameterTypeError(
576  ScriptRunningSetup& setup, ScriptModule* module, int i, int scriptwanted, int provided)
577 {
578  if(setup.PrintErrors) {
579 
580  LOG_ERROR("ScriptExecutor: pass parameters to script failed, func: " +
581  setup.Entryfunction + " param number: " + std::to_string(i) +
582  " script wanted type: " + std::to_string(scriptwanted) + " (" +
583  GetTypeName(scriptwanted) + ") but application provided: " +
584  std::to_string(provided) + " (" + GetTypeName(provided) + ")" +
585  (module ? (" in: " + module->GetInfoString()) : std::string()));
586  }
587 
588  return false;
589 }
590 
591 DLLEXPORT void ScriptExecutor::_DoReceiveParameterTypeError(
592  ScriptRunningSetup& setup, ScriptModule* module, int applicationwanted, int scripthad)
593 {
594  if(setup.PrintErrors) {
595 
596  LOG_ERROR("ScriptExecutor: return parameter from script failed, func: " +
597  setup.Entryfunction +
598  " application wanted type: " + std::to_string(applicationwanted) +
599  " but script return type is: " + std::to_string(scripthad) +
600  (module ? (" in: " + module->GetInfoString()) : std::string()));
601  }
602 }
603 // ------------------------------------ //
605  LErrorReporter& output, asIScriptFunction* func /*= nullptr*/,
606  ScriptModule* scriptmodule /*= nullptr*/)
607 {
608 
609  std::string declaration = ctx->GetExceptionFunction()->GetDeclaration() ?
610  ctx->GetExceptionFunction()->GetDeclaration() :
611  "unknown function";
612 
613  std::string section = ctx->GetExceptionFunction()->GetScriptSectionName() ?
614  ctx->GetExceptionFunction()->GetScriptSectionName() :
615  "unknown";
616 
617  std::string exception =
618  ctx->GetExceptionString() ? ctx->GetExceptionString() : "unknown exception";
619 
620  std::string funcDeclaration =
621  func ? (func->GetDeclaration() ? func->GetDeclaration() : "unknown function") : "";
622 
623  output.Error(
624  std::string("[SCRIPT][EXCEPTION] ") + exception +
625  (func ? std::string(", while running function: ") + funcDeclaration : std::string()) +
626  "\n\t in function " + declaration + " defined in " + section + "(" +
627  std::to_string(ctx->GetExceptionLineNumber()) + ") " +
628  (scriptmodule ? scriptmodule->GetInfoString() : std::string()));
629 
630  PrintCallstack(ctx, output);
631 }
632 
633 DLLEXPORT void ScriptExecutor::PrintCallstack(asIScriptContext* ctx, LErrorReporter& output)
634 {
635 
636  // Print callstack as additional information //
637  output.WriteLine("// ------------------ CallStack ------------------ //");
638 
639  // Loop the stack starting from the frame below the current function
640  // (actually might be nice to print the top frame too)
641  for(asUINT n = 0; n < ctx->GetCallstackSize(); n++) {
642 
643  // Get the function object //
644  const asIScriptFunction* function = ctx->GetFunction(n);
645 
646  // If the function doesn't exist this frame is used internally by the script engine //
647  if(function) {
648 
649  // Check function type //
650  if(function->GetFuncType() == asFUNC_SCRIPT) {
651 
652  // Print info about the script function //
653  output.WriteLine(std::string("\t> ") + function->GetScriptSectionName() + ":" +
654  std::to_string(ctx->GetLineNumber(n)) + " " +
655  function->GetDeclaration());
656 
657  } else {
658  // Info about the application functions //
659  // The context is being reused by the application for a nested call
660  output.WriteLine(
661  std::string("\t> {...Application...}: ") + function->GetDeclaration());
662  }
663  } else {
664  // The context is being reused by the script engine for a nested call
665  output.WriteLine("\t> {...Script internal...}");
666  }
667  }
668 }
669 // ------------------------------------ //
671  const char* str, bool constversion /*= false*/) const
672 {
673  if(!constversion) {
674  return engine->GetTypeIdByDecl(str);
675  } else {
676  // TODO: it would be nice to not have to allocate memory here
677  return engine->GetTypeIdByDecl((std::string("const ") + str).c_str());
678  }
679 }
680 
681 DLLEXPORT asITypeInfo* ScriptExecutor::GetTypeInfo(int type) const
682 {
683  if(type < 0)
684  return nullptr;
685 
686  return engine->GetTypeInfoById(type);
687 }
688 
689 DLLEXPORT std::string ScriptExecutor::GetTypeName(int type) const
690 {
691  if(type < 0)
692  return "error";
693 
694  asITypeInfo* typeInfo = engine->GetTypeInfoById(type);
695 
696  if(!typeInfo)
697  return "error";
698 
699  const auto name = typeInfo->GetName();
700 
701  if(!name)
702  return "error";
703 
704  const auto ns = typeInfo->GetNamespace();
705 
706  std::string result = (ns ? ns : "") + std::string(name);
707 
708  if(type & asTYPEID_OBJHANDLE)
709  result += "@";
710 
711  if(type & asTYPEID_HANDLETOCONST)
712  result = "const " + result;
713 
714  if(type & asTYPEID_MASK_OBJECT)
715  result += " (OBJ)";
716 
717  if(type & asTYPEID_APPOBJECT)
718  result += " (APP)";
719 
720  if(type & asTYPEID_SCRIPTOBJECT)
721  result += " (SCRIPT)";
722 
723  if(type & asTYPEID_TEMPLATE)
724  result = "template " + result;
725 
726  return result;
727 }
728 // ------------------------------------ //
730 {
731  engine->GarbageCollect(asGC_FULL_CYCLE);
732 }
733 // ------------------------------------ //
734 // CustomScriptRun
736 {
737  if(Context) {
738 
739  Exec->_DoneWithContext(Context);
740  }
741 }
DLLEXPORT std::string GetTypeName(int type) const
Access to the builtin types like string and math functions.
DLLEXPORT asIScriptModule * GetModule(Lock &guard)
Builds the script if applicable.
DLLEXPORT void Write(const std::string &data) override
Definition: Logger.cpp:113
DLLEXPORT asIScriptFunction * GetFunctionFromModule(ScriptModule *module, ScriptRunningSetup &parameters)
Finds a script function in module matching setup.
asIScriptContext * RequestContextCallback(asIScriptEngine *engine, void *userdata)
#define LOG_INFO(x)
Definition: Define.h:90
friend void ReturnContextCallback(asIScriptEngine *engine, asIScriptContext *context, void *userdata)
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
#define LOG_ERROR(x)
Definition: Define.h:92
DLLEXPORT std::shared_ptr< ScriptModule > GetScriptModuleByFunction(asIScriptFunction *func, bool reporterror)
Returns module in which script function was defined in.
DLLEXPORT void RunReleaseRefOnObject(void *obj, int objid)
Finds release ref behaviour on object and calls it.
#define LOG_FATAL(x)
Definition: Define.h:94
constexpr auto ANGELSCRIPT_VOID_TYPEID
This has to be constant (and luckily so far it has been)
bool RegisterNotifiersWithAngelScript(asIScriptEngine *engine)
DLLEXPORT int ResolveStringToASID(const char *str, bool constversion=false) const
Converts a string to angelscript type id. Returns -1 on error.
bool BindRendering(asIScriptEngine *engine)
DLLEXPORT std::weak_ptr< ScriptModule > GetModuleByAngelScriptName(const char *nameofmodule)
DLLEXPORT asITypeInfo * GetTypeInfo(int type) const
Returns an asITypeInfo object for type id or null.
Handles ScriptModule creation and AngelScript code execution.
DLLEXPORT void CollectGarbage()
Does a full garbage collection cycle.
bool BindEngineCommon(asIScriptEngine *engine)
static DLLEXPORT void PrintCallstack(asIScriptContext *ctx, LErrorReporter &output)
static DLLEXPORT void PrintExceptionInfo(asIScriptContext *ctx, LErrorReporter &output, asIScriptFunction *func=nullptr, ScriptModule *scrptmodule=nullptr)
Prints exception info and stacktrace to a logger.
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10
#define LOG_WARNING(x)
Definition: Define.h:91
DLLEXPORT std::weak_ptr< ScriptModule > CreateNewModule(const std::string &name, const std::string &source, const int &modulesid=IDFactory::GetID())
DLLEXPORT void PrintFunctionsInModule()
static DLLEXPORT ScriptExecutor * Get()
DLLEXPORT bool DeleteModuleIfNoExternalReferences(int ID)
DLLEXPORT const char * what() const noexcept override
Definition: Exceptions.cpp:29
bool BindStandardFunctions(asIScriptEngine *engine)
Binds standard and other utilities like: std::min, std::max etc.
bool BindTypes(asIScriptEngine *engine)
Definition: TypesBind.cpp:1152
void ReturnContextCallback(asIScriptEngine *engine, asIScriptContext *context, void *userdata)
virtual void WriteLine(const std::string &Text)=0
Default mask for engine classes (some things are accessible even with this off)
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
bool BindGUI(asIScriptEngine *engine)
void ScriptMessageCallback(const asSMessageInfo *msg, void *param)
virtual void Error(const std::string &Text)=0
#define DLLEXPORT
Definition: Include.h:84
DLLEXPORT void _DoneWithContext(asIScriptContext *context)
Called after a script has been executed and the context is no longer needed.
DLLEXPORT std::unique_ptr< CustomScriptRun > PrepareCustomScriptRun(asIScriptFunction *func, ScriptRunningSetup extraoptions=ScriptRunningSetup())
Starts a script run that supports custom argument passing.
static DLLEXPORT Engine * GetEngine()
Definition: Engine.cpp:81
DLLEXPORT std::weak_ptr< ScriptModule > GetModule(const int &ID)
DLLEXPORT void DeleteModule(ScriptModule *ptrtomatch)
bool BindPhysics(asIScriptEngine *engine)
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
friend asIScriptContext * RequestContextCallback(asIScriptEngine *engine, void *userdata)
bool BindEntity(asIScriptEngine *engine)
Definition: EntityBind.cpp:565
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
DLLEXPORT asIScriptContext * _GetContextForExecution()
Called when a context is required for script execution.
asIScriptContext * Context
DLLEXPORT std::string GetInfoString()