Leviathan  0.8.0.0
Leviathan game engine
Leviathan::ScriptExecutor Class Reference

Handles ScriptModule creation and AngelScript code execution. More...

#include <ScriptExecutor.h>

Public Member Functions

DLLEXPORT ScriptExecutor ()
 
DLLEXPORT ~ScriptExecutor ()
 
DLLEXPORT std::weak_ptr< ScriptModuleCreateNewModule (const std::string &name, const std::string &source, const int &modulesid=IDFactory::GetID())
 
DLLEXPORT void DeleteModule (ScriptModule *ptrtomatch)
 
DLLEXPORT bool DeleteModuleIfNoExternalReferences (int ID)
 
DLLEXPORT std::weak_ptr< ScriptModuleGetModule (const int &ID)
 
DLLEXPORT std::weak_ptr< ScriptModuleGetModuleByAngelScriptName (const char *nameofmodule)
 
template<typename ReturnT , class... Args>
ScriptRunResult< ReturnT > RunScript (const std::shared_ptr< ScriptModule > &module, ScriptRunningSetup &parameters, Args &&... args)
 Runs a function in a script. More...
 
template<typename ReturnT , class... Args>
ScriptRunResult< ReturnT > RunScript (asIScriptFunction *func, std::shared_ptr< ScriptModule > module, ScriptRunningSetup &parameters, Args &&... args)
 Runs a function in a script (that is known already) More...
 
template<typename ReturnT , class... Args>
ScriptRunResult< ReturnT > RunScriptMethod (ScriptRunningSetup &parameters, asIScriptFunction *func, void *obj, Args &&... args)
 Runs a method in a script. More...
 
DLLEXPORT std::unique_ptr< CustomScriptRunPrepareCustomScriptRun (asIScriptFunction *func, ScriptRunningSetup extraoptions=ScriptRunningSetup())
 Starts a script run that supports custom argument passing. More...
 
template<typename ReturnT >
ScriptRunResult< ReturnT > ExecuteCustomRun (const std::unique_ptr< CustomScriptRun > &run)
 Ends a custom script run by actually executing the script and returning a value. More...
 
DLLEXPORT void RunReleaseRefOnObject (void *obj, int objid)
 Finds release ref behaviour on object and calls it. More...
 
DLLEXPORT std::shared_ptr< ScriptModuleGetScriptModuleByFunction (asIScriptFunction *func, bool reporterror)
 Returns module in which script function was defined in. More...
 
DLLEXPORT asIScriptFunction * GetFunctionFromModule (ScriptModule *module, ScriptRunningSetup &parameters)
 Finds a script function in module matching setup. More...
 
DLLEXPORT int ResolveStringToASID (const char *str) const
 Converts a string to angelscript type id. Returns -1 on error. More...
 
DLLEXPORT asITypeInfo * GetTypeInfo (int type) const
 Returns an asITypeInfo object for type id or null. More...
 
DLLEXPORT asITypeInfo * GetTypeInfoByDecl (const char *str) const
 Returns an asITypeInfo object for type name or null. More...
 
DLLEXPORT asIScriptEngine * GetASEngine ()
 
DLLEXPORT void CollectGarbage ()
 Does a full garbage collection cycle. More...
 

Static Public Member Functions

static DLLEXPORT void PrintExceptionInfo (asIScriptContext *ctx, LErrorReporter &output, asIScriptFunction *func=nullptr, ScriptModule *scrptmodule=nullptr)
 Prints exception info and stacktrace to a logger. More...
 
static DLLEXPORT void PrintCallstack (asIScriptContext *ctx, LErrorReporter &output)
 
static DLLEXPORT ScriptExecutorGet ()
 

Protected Member Functions

DLLEXPORT void _DoneWithContext (asIScriptContext *context)
 Called after a script has been executed and the context is no longer needed. More...
 

Detailed Description

Handles ScriptModule creation and AngelScript code execution.

Definition at line 55 of file ScriptExecutor.h.

Constructor & Destructor Documentation

◆ ScriptExecutor()

ScriptExecutor::ScriptExecutor ( )

Definition at line 101 of file ScriptExecutor.cpp.

101  : engine(nullptr), AllocatedScriptModules()
102 {
103 
104  instance = this;
105 
106  // Initialize AngelScript //
107  engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
108  if(engine == nullptr) {
109 
110  Logger::Get()->Error("ScriptExecutor: Init: asCreateScriptEngine failed");
111  Logger::Get()->Info("ScriptExecutor: tried to init angelscript version " +
112  Convert::ToString(ANGELSCRIPT_VERSION));
113  Logger::Get()->Write("Did you use a wrong angelscript version? copy header files to "
114  "leviathan/Angelscript/include from your angelscript.zip");
115  throw Exception("Failed to init angelscript");
116  }
117 
118  // set callback to error report function //
119  engine->SetMessageCallback(asFUNCTION(ScriptMessageCallback), 0, asCALL_CDECL);
120 
121  // The ScriptExecutor can be retrieved from asIScriptEngine user data
122  engine->SetUserData(this);
123 
124 #ifdef ANGELSCRIPT_HAS_TRANSLATE_CALLBACK
125  // Set error translation callback
126  engine->SetTranslateAppExceptionCallback(
127  asFUNCTION(ScriptTranslateExceptionCallback), nullptr, asCALL_CDECL);
128 #endif // ANGELSCRIPT_HAS_TRANSLATE_CALLBACK
129 
130 
131  // Builtins are in this access group //
132  const auto initialMask =
133  engine->SetDefaultAccessMask(static_cast<AccessFlags>(ScriptAccess::Builtin));
134 
135  // math functions //
136  RegisterScriptMath(engine);
137  RegisterScriptMathComplex(engine);
138 
139  // register script string type //
140  RegisterStdString(engine);
141  RegisterScriptArray(engine, true);
142  // register other script extensions //
143  RegisterStdStringUtils(engine);
144 
145 
146  RegisterScriptDateTime(engine);
147 
148  // register dictionary object //
149  RegisterScriptDictionary(engine);
150 
151  // Register the grid addon //
152  RegisterScriptGrid(engine);
153 
154  // Register reference handles //
155  RegisterScriptHandle(engine);
156 
157  RegisterScriptWeakRef(engine);
158 
159  RegisterScriptAny(engine);
160 
161  // Put the extended standard stuff also in Builtin access mask
162 
163  if(!BindStandardFunctions(engine))
164  throw Exception("BindStandardFunctions failed");
165 
166  // All normal engine stuff is in the DefaultEngine access mask //
167  engine->SetDefaultAccessMask(static_cast<AccessFlags>(ScriptAccess::DefaultEngine));
168 
169  if(!BindOgre(engine))
170  throw Exception("BindOgre failed");
171 
172  if(!BindNewton(engine))
173  throw Exception("BindNewton failed");
174 
175  if(!BindTypes(engine))
176  throw Exception("BindTypes failed");
177 
178  if(!BindEngineCommon(engine))
179  throw Exception("BindEngineCommon failed");
180 
181  if(!BindGUI(engine))
182  throw Exception("BindGUI failed");
183 
184  if(!BindEntity(engine))
185  throw Exception("BindEntity failed");
186 
187  // Bind notifiers //
188  if(!RegisterNotifiersWithAngelScript(engine)) {
189  // failed //
190  LOG_ERROR("ScriptExecutor: Init: AngelScript: register Notifier types failed");
191  throw Exception("Script bind failed");
192  }
193 
194  // Restore the default mask to let the application do what it wants with the masks
195  engine->SetDefaultAccessMask(initialMask);
196 
197  // bind application specific //
198  auto leviathanengine = Engine::GetEngine();
199 
200  if(leviathanengine) {
201 
202  if(!leviathanengine->GetOwningApplication()->InitLoadCustomScriptTypes(engine)) {
203 
204  LOG_ERROR("ScriptExecutor: Init: AngelScript: application register failed");
205  throw Exception("Script bind failed");
206  }
207  }
208 
209  // Verify void type //
210  const auto actualVoid = engine->GetTypeIdByDecl("void");
211  if(actualVoid != ANGELSCRIPT_VOID_TYPEID) {
212 
213  LOG_FATAL("ScriptExecutor: angelscript void type has changed! expected " +
214  std::to_string(ANGELSCRIPT_VOID_TYPEID) +
215  " (constexpr) == " + std::to_string(actualVoid) + " (actual value)");
216  }
217 }
Access to the builtin types like string and math functions.
DLLEXPORT void Write(const std::string &data) override
Definition: Logger.cpp:113
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
#define LOG_ERROR(x)
Definition: Define.h:83
#define LOG_FATAL(x)
Definition: Define.h:85
constexpr auto ANGELSCRIPT_VOID_TYPEID
This has to be constant (and luckily so far it has been)
bool RegisterNotifiersWithAngelScript(asIScriptEngine *engine)
bool BindEngineCommon(asIScriptEngine *engine)
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10
bool BindStandardFunctions(asIScriptEngine *engine)
Binds standard and other utilities like: std::min, std::max etc.
bool BindTypes(asIScriptEngine *engine)
Definition: TypesBind.cpp:804
bool BindNewton(asIScriptEngine *engine)
Definition: NewtonBind.cpp:57
Default mask for engine classes (some things are accessible even with this off)
static std::string ToString(const T &val)
Definition: Convert.h:72
bool BindOgre(asIScriptEngine *engine)
Definition: OgreBind.cpp:621
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
bool BindGUI(asIScriptEngine *engine)
void ScriptMessageCallback(const asSMessageInfo *msg, void *param)
static DLLEXPORT Engine * GetEngine()
Definition: Engine.cpp:77
bool BindEntity(asIScriptEngine *engine)
Definition: EntityBind.cpp:628
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177

◆ ~ScriptExecutor()

ScriptExecutor::~ScriptExecutor ( )

Definition at line 218 of file ScriptExecutor.cpp.

219 {
220  {
221  Lock lock(ModulesLock);
222  auto end = AllocatedScriptModules.end();
223  for(auto iter = AllocatedScriptModules.begin(); iter != end; ++iter) {
224 
225  (*iter)->Release();
226  }
227 
228  // release/delete all modules //
229  AllocatedScriptModules.clear();
230  }
231 
232  // release AngelScript //
233  if(engine) {
234 
235  engine->Release();
236  engine = nullptr;
237  }
238 
239  instance = nullptr;
240 }
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:15

Member Function Documentation

◆ _DoneWithContext()

DLLEXPORT void Leviathan::ScriptExecutor::_DoneWithContext ( asIScriptContext *  context)
protected

Called after a script has been executed and the context is no longer needed.

Note
Also called from CustomScriptRun

Definition at line 451 of file ScriptExecutor.cpp.

452 {
453  context->Release();
454 }

◆ CollectGarbage()

DLLEXPORT void ScriptExecutor::CollectGarbage ( )

Does a full garbage collection cycle.

Definition at line 650 of file ScriptExecutor.cpp.

651 {
652  engine->GarbageCollect(asGC_FULL_CYCLE);
653 }

◆ CreateNewModule()

DLLEXPORT std::weak_ptr< ScriptModule > Leviathan::ScriptExecutor::CreateNewModule ( const std::string &  name,
const std::string &  source,
const int &  modulesid = IDFactory::GetID() 
)

Definition at line 486 of file ScriptExecutor.cpp.

489 {
490  // create new module to a smart pointer //
491  auto tmpptr = std::make_shared<ScriptModule>(engine, name, modulesid, source);
492 
493  // add to vector and return //
494  Lock lock(ModulesLock);
495  AllocatedScriptModules.push_back(tmpptr);
496  return tmpptr;
497 }
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:15

◆ DeleteModule()

DLLEXPORT void Leviathan::ScriptExecutor::DeleteModule ( ScriptModule ptrtomatch)

Definition at line 499 of file ScriptExecutor.cpp.

500 {
501 
502  Lock lock(ModulesLock);
503 
504  // find module based on pointer and remove //
505  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
506  if(AllocatedScriptModules[i].get() == ptrtomatch) {
507 
508  AllocatedScriptModules[i]->Release();
509  // remove //
510  AllocatedScriptModules.erase(AllocatedScriptModules.begin() + i);
511  return;
512  }
513  }
514 }
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:15

◆ DeleteModuleIfNoExternalReferences()

DLLEXPORT bool Leviathan::ScriptExecutor::DeleteModuleIfNoExternalReferences ( int  ID)

Definition at line 516 of file ScriptExecutor.cpp.

517 {
518 
519  Lock lock(ModulesLock);
520 
521  // Find based on the id //
522  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
523  if(AllocatedScriptModules[i]->GetID() == ID) {
524  // Check reference count //
525  if(AllocatedScriptModules[i].use_count() != 1) {
526  // Other references exist //
527  return false;
528  }
529 
530  AllocatedScriptModules[i]->Release();
531 
532  // remove //
533  AllocatedScriptModules.erase(AllocatedScriptModules.begin() + i);
534  return true;
535  }
536  }
537  // Nothing found //
538  return false;
539 }
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:15

◆ ExecuteCustomRun()

template<typename ReturnT >
ScriptRunResult<ReturnT> Leviathan::ScriptExecutor::ExecuteCustomRun ( const std::unique_ptr< CustomScriptRun > &  run)
inline

Ends a custom script run by actually executing the script and returning a value.

Note
You MUST manually pass arguments before calling this! Use RunScript if you don't need custom argument passing

Definition at line 216 of file ScriptExecutor.h.

217  {
218  if(!run)
219  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
220 
221  // Run the script //
222  // TODO: timeout and debugging registering with linecallbacks here //
223  int retcode = run->Context->Execute();
224 
225  // Get the return value //
226  auto returnvalue = _HandleEndedScriptExecution<ReturnT>(
227  retcode, run->Context, run->Setup, run->Func, run->Module.get());
228 
229  // Release the context //
230  _DoneWithContext(run->Context);
231  run->Context = nullptr;
232 
233  // Return the returned value //
234  return returnvalue;
235  }
DLLEXPORT void _DoneWithContext(asIScriptContext *context)
Called after a script has been executed and the context is no longer needed.

◆ Get()

DLLEXPORT ScriptExecutor * Leviathan::ScriptExecutor::Get ( )
static
Note
Alternative way to get ScriptExecutor is from asIScriptEngine::GetUserData

Definition at line 242 of file ScriptExecutor.cpp.

243 {
244  return instance;
245 }

◆ GetASEngine()

DLLEXPORT asIScriptEngine* Leviathan::ScriptExecutor::GetASEngine ( )
inline

Definition at line 269 of file ScriptExecutor.h.

270  {
271  return engine;
272  }

◆ GetFunctionFromModule()

DLLEXPORT asIScriptFunction * ScriptExecutor::GetFunctionFromModule ( ScriptModule module,
ScriptRunningSetup parameters 
)

Finds a script function in module matching setup.

Returns
The function or null if not found or module is invalid

Sets the function existed in the parameters

Definition at line 249 of file ScriptExecutor.cpp.

251 {
252  if(!module) {
253 
254  if(parameters.PrintErrors) {
255  Logger::Get()->Error("ScriptExecutor: GetFunctionFromModule: module is nullptr");
256  }
257 
258  return nullptr;
259  }
260 
261  asIScriptFunction* func;
262 
263  asIScriptModule* asModule = module->GetModule();
264 
265  if(!asModule) {
266 
267  if(parameters.PrintErrors) {
268  Logger::Get()->Error(
269  "ScriptExecutor: GetFunctionFromModule: cannot get function from "
270  "an invalid script module: " +
271  module->GetInfoString());
272  }
273 
274  return nullptr;
275  }
276 
277  // Get the entry function from the module //
278  if(!parameters.FullDeclaration) {
279 
280  func = asModule->GetFunctionByName(parameters.Entryfunction.c_str());
281 
282  } else {
283 
284  func = asModule->GetFunctionByDecl(parameters.Entryfunction.c_str());
285  }
286 
287  if(!_CheckScriptFunctionPtr(func, parameters, module)) {
288 
289  return nullptr;
290  }
291 
292  return func;
293 }
DLLEXPORT asIScriptModule * GetModule(Lock &guard)
Builds the script if applicable.
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
DLLEXPORT std::string GetInfoString()

◆ GetModule()

DLLEXPORT std::weak_ptr< ScriptModule > Leviathan::ScriptExecutor::GetModule ( const int &  ID)

Definition at line 456 of file ScriptExecutor.cpp.

457 {
458  // loop modules and return a ptr to matching id //
459  Lock lock(ModulesLock);
460 
461  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
462  if(AllocatedScriptModules[i]->GetID() == ID)
463  return AllocatedScriptModules[i];
464  }
465 
466  return std::shared_ptr<ScriptModule>(nullptr);
467 }
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:15

◆ GetModuleByAngelScriptName()

DLLEXPORT std::weak_ptr< ScriptModule > Leviathan::ScriptExecutor::GetModuleByAngelScriptName ( const char *  nameofmodule)

Definition at line 469 of file ScriptExecutor.cpp.

471 {
472  // Find a matching name //
473  std::string module(nameofmodule);
474 
475  Lock lock(ModulesLock);
476 
477  // TODO: check could this be checked by comparing pointers
478  for(size_t i = 0; i < AllocatedScriptModules.size(); i++) {
479  if(AllocatedScriptModules[i]->GetModuleName() == module)
480  return AllocatedScriptModules[i];
481  }
482 
483  return std::shared_ptr<ScriptModule>(nullptr);
484 }
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:15

◆ GetScriptModuleByFunction()

DLLEXPORT std::shared_ptr< ScriptModule > ScriptExecutor::GetScriptModuleByFunction ( asIScriptFunction *  func,
bool  reporterror 
)

Returns module in which script function was defined in.

Todo:
When module is null find the module by AngelScript module pointer (set the userdata pointer on the module to point to the ScriptModule object) for faster finding

Definition at line 363 of file ScriptExecutor.cpp.

365 {
366  const char* nameStr = func->GetModuleName();
367 
368  if(!nameStr || strlen(nameStr) <= 1)
369  return nullptr;
370 
371  // static_cast<ScriptModule*>(func->GetModule()->GetUserData());
372  // then find by pointer in valid script modules
373 
374  std::shared_ptr<ScriptModule> module =
375  GetModuleByAngelScriptName(func->GetModuleName()).lock();
376 
377  if(!module) {
378 
379  if(reporterror) {
380  LOG_WARNING("ScriptExecutor: GetScriptModuleByFunction: the module is no longer "
381  "available: " +
382  std::string(func->GetModuleName()));
383  }
384  }
385 
386  return module;
387 }
DLLEXPORT std::weak_ptr< ScriptModule > GetModuleByAngelScriptName(const char *nameofmodule)
#define LOG_WARNING(x)
Definition: Define.h:82

◆ GetTypeInfo()

DLLEXPORT asITypeInfo * ScriptExecutor::GetTypeInfo ( int  type) const

Returns an asITypeInfo object for type id or null.

Definition at line 641 of file ScriptExecutor.cpp.

642 {
643 
644  if(type < 0)
645  return nullptr;
646 
647  return engine->GetTypeInfoById(type);
648 }

◆ GetTypeInfoByDecl()

DLLEXPORT asITypeInfo* Leviathan::ScriptExecutor::GetTypeInfoByDecl ( const char *  str) const

Returns an asITypeInfo object for type name or null.

◆ PrepareCustomScriptRun()

DLLEXPORT std::unique_ptr< CustomScriptRun > ScriptExecutor::PrepareCustomScriptRun ( asIScriptFunction *  func,
ScriptRunningSetup  extraoptions = ScriptRunningSetup() 
)

Starts a script run that supports custom argument passing.

Definition at line 330 of file ScriptExecutor.cpp.

332 {
333  if(!func)
334  return nullptr;
335 
336  auto run = std::make_unique<CustomScriptRun>(this);
337  run->Setup = extraoptions;
338  run->Func = func;
339 
340  // // TODO: this is a performance waste if there are no errors
341  // std::shared_ptr<ScriptModule> module =
342  // GetScriptModuleByFunction(func, run->Setup.PrintErrors);
343 
344  // Create a running context for the function //
345  run->Context = _GetContextForExecution();
346 
347  if(!run->Context) {
348  // Should this be fatal?
349  LOG_ERROR("ScriptExecutor: PrepareCustomScriptRun: failed to create a new context");
350  return nullptr;
351  }
352 
353  if(!_PrepareContextForPassingParameters(
354  func, run->Context, run->Setup, run->Module.get())) {
355 
356  _DoneWithContext(run->Context);
357  return nullptr;
358  }
359 
360  return run;
361 }
#define LOG_ERROR(x)
Definition: Define.h:83
DLLEXPORT void _DoneWithContext(asIScriptContext *context)
Called after a script has been executed and the context is no longer needed.

◆ PrintCallstack()

DLLEXPORT void ScriptExecutor::PrintCallstack ( asIScriptContext *  ctx,
LErrorReporter output 
)
static

Definition at line 598 of file ScriptExecutor.cpp.

599 {
600 
601  // Print callstack as additional information //
602  output.WriteLine("// ------------------ CallStack ------------------ //");
603 
604  // Loop the stack starting from the frame below the current function
605  // (actually might be nice to print the top frame too)
606  for(asUINT n = 0; n < ctx->GetCallstackSize(); n++) {
607 
608  // Get the function object //
609  const asIScriptFunction* function = ctx->GetFunction(n);
610 
611  // If the function doesn't exist this frame is used internally by the script engine //
612  if(function) {
613 
614  // Check function type //
615  if(function->GetFuncType() == asFUNC_SCRIPT) {
616 
617  // Print info about the script function //
618  output.WriteLine(std::string("\t> ") + function->GetScriptSectionName() + ":" +
619  std::to_string(ctx->GetLineNumber(n)) + " " +
620  function->GetDeclaration());
621 
622  } else {
623  // Info about the application functions //
624  // The context is being reused by the application for a nested call
625  output.WriteLine(
626  std::string("\t> {...Application...}: ") + function->GetDeclaration());
627  }
628  } else {
629  // The context is being reused by the script engine for a nested call
630  output.WriteLine("\t> {...Script internal...}");
631  }
632  }
633 }
virtual void WriteLine(const std::string &Text)=0

◆ PrintExceptionInfo()

DLLEXPORT void ScriptExecutor::PrintExceptionInfo ( asIScriptContext *  ctx,
LErrorReporter output,
asIScriptFunction *  func = nullptr,
ScriptModule scrptmodule = nullptr 
)
static

Prints exception info and stacktrace to a logger.

Definition at line 569 of file ScriptExecutor.cpp.

572 {
573 
574  std::string declaration = ctx->GetExceptionFunction()->GetDeclaration() ?
575  ctx->GetExceptionFunction()->GetDeclaration() :
576  "unknown function";
577 
578  std::string section = ctx->GetExceptionFunction()->GetScriptSectionName() ?
579  ctx->GetExceptionFunction()->GetScriptSectionName() :
580  "unknown";
581 
582  std::string exception =
583  ctx->GetExceptionString() ? ctx->GetExceptionString() : "unknown exception";
584 
585  std::string funcDeclaration =
586  func ? (func->GetDeclaration() ? func->GetDeclaration() : "unknown function") : "";
587 
588  output.Error(
589  std::string("[SCRIPT][EXCEPTION] ") + exception +
590  (func ? std::string(", while running function: ") + funcDeclaration : std::string()) +
591  "\n\t in function " + declaration + " defined in " + section + "(" +
592  std::to_string(ctx->GetExceptionLineNumber()) + ") " +
593  (scriptmodule ? scriptmodule->GetInfoString() : std::string()));
594 
595  PrintCallstack(ctx, output);
596 }
static DLLEXPORT void PrintCallstack(asIScriptContext *ctx, LErrorReporter &output)
virtual void Error(const std::string &Text)=0

◆ ResolveStringToASID()

DLLEXPORT int ScriptExecutor::ResolveStringToASID ( const char *  str) const

Converts a string to angelscript type id. Returns -1 on error.

Replaces GetAngelScriptTypeID

Definition at line 635 of file ScriptExecutor.cpp.

636 {
637 
638  return engine->GetTypeIdByDecl(str);
639 }

◆ RunReleaseRefOnObject()

DLLEXPORT void ScriptExecutor::RunReleaseRefOnObject ( void *  obj,
int  objid 
)

Finds release ref behaviour on object and calls it.

Exceptions
Exceptionif it didn't work
Note
Should only be called if the object of type has asOBJ_REF and no asOBJ_NOCOUNT
Todo:
This is actually a method in the angelscript engine, so use that, but this is a good example how to run any behaviour

Definition at line 295 of file ScriptExecutor.cpp.

296 {
297  asITypeInfo* info = engine->GetTypeInfoById(objid);
298 
299  asUINT count = info->GetBehaviourCount();
300 
301  for(asUINT i = 0; i < count; ++i) {
302 
303  asEBehaviours behaviour;
304  asIScriptFunction* func = info->GetBehaviourByIndex(i, &behaviour);
305 
306  if(!func) {
307 
308  LOG_ERROR("ScriptExecutor: RunReleaseRefOnObject: failed to get behaviour");
309  continue;
310  }
311 
312  if(behaviour == asBEHAVE_RELEASE) {
313 
314  LOG_INFO(
315  "ScriptExecutor: RunReleaseRefOnObject: Found asBEHAVE_RELEASE, calling it");
316 
317  ScriptRunningSetup ssetup;
318  const auto result = RunScriptMethod<void>(ssetup, func, obj);
319 
320  if(result.Result != SCRIPT_RUN_RESULT::Success)
321  throw Exception("Failed to run release behaviour");
322 
323  return;
324  }
325  }
326 
327  throw Exception("Didn't find release ref behaviour on object type");
328 }
#define LOG_INFO(x)
Definition: Define.h:81
#define LOG_ERROR(x)
Definition: Define.h:83
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10

◆ RunScript() [1/2]

template<typename ReturnT , class... Args>
ScriptRunResult<ReturnT> Leviathan::ScriptExecutor::RunScript ( const std::shared_ptr< ScriptModule > &  module,
ScriptRunningSetup parameters,
Args &&...  args 
)
inline

Runs a function in a script.

Note
This is the recommended way to run scripts (other than GameModule that has its own method)
Todo:

Allow recursive calls and more context reuse. Also wrap context in an object that automatically returns it in case of expections (_HandleEndedScriptExecution can throw)

Also make all the script module using functions automatically get it if they need for error reporting

Definition at line 80 of file ScriptExecutor.h.

82  {
83  // This calls _CheckScriptFunctionPtr
84  asIScriptFunction* func = GetFunctionFromModule(module.get(), parameters);
85 
86  return RunScript<ReturnT>(func, module, parameters, std::forward<Args>(args)...);
87  }
DLLEXPORT asIScriptFunction * GetFunctionFromModule(ScriptModule *module, ScriptRunningSetup &parameters)
Finds a script function in module matching setup.

◆ RunScript() [2/2]

template<typename ReturnT , class... Args>
ScriptRunResult<ReturnT> Leviathan::ScriptExecutor::RunScript ( asIScriptFunction *  func,
std::shared_ptr< ScriptModule module,
ScriptRunningSetup parameters,
Args &&...  args 
)
inline

Runs a function in a script (that is known already)

Todo:
Wrap context in an object that automatically returns it in case of expections (_HandleEndedScriptExecution can throw)

Definition at line 93 of file ScriptExecutor.h.

95  {
96  if(!func)
97  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
98 
99  if(!module) {
100  // Find the right module //
101  module = GetScriptModuleByFunction(func, parameters.PrintErrors);
102  }
103 
104 
105  // Create a running context for the function //
106  asIScriptContext* scriptContext = _GetContextForExecution();
107 
108  if(!scriptContext) {
109  // Should this be fatal?
110  LOG_ERROR("ScriptExecutor: RunScript: failed to create a new context");
111  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
112  }
113 
114  if(!_PrepareContextForPassingParameters(
115  func, scriptContext, parameters, module.get())) {
116 
117  _DoneWithContext(scriptContext);
118  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
119  }
120 
121  // Pass the parameters //
122  if(!_PassParametersToScript(
123  scriptContext, parameters, module.get(), func, std::forward<Args>(args)...)) {
124 
125  // Failed passing the parameters //
126  _DoneWithContext(scriptContext);
127  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
128  }
129 
130  // Run the script //
131  // TODO: timeout and debugging registering with linecallbacks here //
132  int retcode = scriptContext->Execute();
133 
134  // Get the return value //
135  auto returnvalue = _HandleEndedScriptExecution<ReturnT>(
136  retcode, scriptContext, parameters, func, module.get());
137 
138  // Release the context //
139  _DoneWithContext(scriptContext);
140 
141  // Return the returned value //
142  return returnvalue;
143  }
#define LOG_ERROR(x)
Definition: Define.h:83
DLLEXPORT std::shared_ptr< ScriptModule > GetScriptModuleByFunction(asIScriptFunction *func, bool reporterror)
Returns module in which script function was defined in.
DLLEXPORT void _DoneWithContext(asIScriptContext *context)
Called after a script has been executed and the context is no longer needed.

◆ RunScriptMethod()

template<typename ReturnT , class... Args>
ScriptRunResult<ReturnT> Leviathan::ScriptExecutor::RunScriptMethod ( ScriptRunningSetup parameters,
asIScriptFunction *  func,
void *  obj,
Args &&...  args 
)
inline

Runs a method in a script.

Note
This doesn't verify that the object type is correct for the function. The caller is responsible for making sure that func is part of the class of obj
The parameters object is largely ignored (function name)
Todo:
Merge common parts with RunScript

Definition at line 151 of file ScriptExecutor.h.

153  {
154  if(!func || !obj)
155  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
156 
157  // TODO: this is a performance waste if there are no errors
158  std::shared_ptr<ScriptModule> module =
159  GetScriptModuleByFunction(func, parameters.PrintErrors);
160 
161  // Create a running context for the function //
162  asIScriptContext* scriptContext = _GetContextForExecution();
163 
164  if(!scriptContext) {
165  // Should this be fatal?
166  LOG_ERROR("ScriptExecutor: RunScriptMethod: failed to create a new context");
167  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
168  }
169 
170  if(!_PrepareContextForPassingParameters(
171  func, scriptContext, parameters, module.get())) {
172 
173  _DoneWithContext(scriptContext);
174  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
175  }
176 
177  // Pass the parameters //
178  if(!_PassParametersToScript(
179  scriptContext, parameters, module.get(), func, std::forward<Args>(args)...)) {
180 
181  // Failed passing the parameters //
182  _DoneWithContext(scriptContext);
183  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
184  }
185 
186  // Pass the object instance //
187  if(scriptContext->SetObject(obj) < 0) {
188 
189  _DoneWithContext(scriptContext);
190  return ScriptRunResult<ReturnT>(SCRIPT_RUN_RESULT::Error);
191  }
192 
193  // Run the script //
194  // TODO: timeout and debugging registering with linecallbacks here //
195  int retcode = scriptContext->Execute();
196 
197  // Get the return value //
198  auto returnvalue = _HandleEndedScriptExecution<ReturnT>(
199  retcode, scriptContext, parameters, func, module.get());
200 
201  // Release the context //
202  _DoneWithContext(scriptContext);
203 
204  // Return the returned value //
205  return returnvalue;
206  }
#define LOG_ERROR(x)
Definition: Define.h:83
DLLEXPORT std::shared_ptr< ScriptModule > GetScriptModuleByFunction(asIScriptFunction *func, bool reporterror)
Returns module in which script function was defined in.
DLLEXPORT void _DoneWithContext(asIScriptContext *context)
Called after a script has been executed and the context is no longer needed.

The documentation for this class was generated from the following files: