29 #include "scriptstdstring/scriptstdstring.h"
30 #include "scriptmath/scriptmath.h"
31 #include "scriptany/scriptany.h"
32 #include "scriptarray/scriptarray.h"
33 #include "scripthelper/scripthelper.h"
38 #include <curl/curl.h>
40 #include <curl/easy.h>
64 using namespace AngelScript;
70 case ScriptCategory::INVALID:
return "INVALID";
71 case ScriptCategory::ACTOR:
return "ACTOR";
72 case ScriptCategory::TERRAIN:
return "TERRAIN";
73 case ScriptCategory::CUSTOM:
return "CUSTOM";
78 ScriptUnit::ScriptUnit()
83 ScriptUnit::~ScriptUnit()
97 ScriptEngine::ScriptEngine() :
121 SLOG(
"ScriptEngine initializing ...");
125 engine = AngelScript::asCreateScriptEngine(ANGELSCRIPT_VERSION);
127 engine->SetEngineProperty(AngelScript::asEP_ALLOW_UNSAFE_REFERENCES,
true);
136 if (result == AngelScript::asINVALID_ARG)
138 SLOG(
"One of the arguments is incorrect, e.g. obj is null for a class method.");
141 else if (result == AngelScript::asNOT_SUPPORTED)
143 SLOG(
" The arguments are not supported, e.g. asCALL_GENERIC.");
146 SLOG(
"Unkown error while setting up message callback");
154 AngelScript::RegisterScriptArray(
engine,
true);
155 AngelScript::RegisterStdString(
engine);
156 AngelScript::RegisterStdStringUtils(
engine);
157 AngelScript::RegisterScriptMath(
engine);
158 static float SCRIPT_FLT_MAX = FLT_MAX;
159 static int SCRIPT_INT_MAX = INT_MAX;
160 result =
engine->RegisterGlobalProperty(
"const float FLT_MAX", &SCRIPT_FLT_MAX);
ROR_ASSERT( result >= 0 );
161 result =
engine->RegisterGlobalProperty(
"const int INT_MAX", &SCRIPT_INT_MAX);
ROR_ASSERT(result >= 0);
162 AngelScript::RegisterScriptAny(
engine);
163 AngelScript::RegisterScriptDictionary(
engine);
166 result =
engine->RegisterGlobalFunction(
"void log(const string &in)", AngelScript::asFUNCTION(
logString), AngelScript::asCALL_CDECL);
ROR_ASSERT( result >= 0 );
167 result =
engine->RegisterGlobalFunction(
"void print(const string &in)", AngelScript::asFUNCTION(
logString), AngelScript::asCALL_CDECL);
ROR_ASSERT( result >= 0 );
192 SLOG(
"Type registrations done. If you see no error above everything should be working");
199 const char *type =
"Error";
200 if ( msg->type == AngelScript::asMSGTYPE_INFORMATION )
202 else if ( msg->type == AngelScript::asMSGTYPE_WARNING )
206 sprintf(tmp,
"%s (%d, %d): %s = %s", msg->section, msg->row, msg->col, type, msg->message);
211 msg->section, msg->message);
214 std::string
ptr2str(
const char* ptr) {
if (ptr)
return ptr;
else return ""; }
218 std::string funcName, funcObjTypeName, objName;
219 if (ctx->GetFunction())
221 funcName =
ptr2str(ctx->GetFunction()->GetName());
222 objName =
ptr2str(ctx->GetFunction()->GetObjectName());
223 if (ctx->GetFunction()->GetObjectType())
224 funcObjTypeName =
ptr2str(ctx->GetFunction()->GetObjectType()->GetName());
230 funcName, funcObjTypeName, objName
237 std::string funcName;
238 if (ctx->GetExceptionFunction())
240 funcName =
ptr2str(ctx->GetExceptionFunction()->GetName());
244 funcName, ctx->GetExceptionString());
296 SLOG(
fmt::format(
"Warning: Could not attach LineCallback to NID {}, error code {}; continuing without it...", result, nid));
306 SLOG(
fmt::format(
"Warning: Could not attach ExceptionCallback to NID {}, error code {}; continuing without it...", result, nid));
312 int result =
context->Execute();
315 if ( result != AngelScript::asEXECUTION_FINISHED )
318 if ( result == AngelScript::asEXECUTION_ABORTED )
320 SLOG(
"The script was aborted before it could finish. Probably it timed out.");
322 else if ( result == AngelScript::asEXECUTION_EXCEPTION )
326 SLOG(
"The script ended with exception; details below:");
328 SLOG(
"\tcontext.ExceptionLineNumber: " +
TOSTRING(
context->GetExceptionLineNumber()));
329 SLOG(
"\tcontext.ExceptionString: " +
ptr2str(
context->GetExceptionString()));
330 AngelScript::asIScriptFunction* func =
context->GetExceptionFunction();
333 SLOG(
"\tcontext.ExceptionFunction.Declaration: " +
ptr2str(func->GetDeclaration()));
334 SLOG(
"\tcontext.ExceptionFunction.ModuleName: " +
ptr2str(func->GetModuleName()));
335 SLOG(
"\tcontext.ExceptionFunction.ScriptSectionName: " +
ptr2str(func->GetScriptSectionName()));
336 SLOG(
"\tcontext.ExceptionFunction.ObjectName: " +
ptr2str(func->GetObjectName()));
339 else if (result == AngelScript::asCONTEXT_NOT_PREPARED)
343 SLOG(
fmt::format(
"The script ended with error code asCONTEXT_NOT_PREPARED; Function to execute: {},currently triggered event: {}, NID: {}",
348 SLOG(
fmt::format(
"The script ended with error code asCONTEXT_NOT_PREPARED; Function to execute NOT SET,currently triggered event: {}, NID: {}",
354 SLOG(
"The script ended for some unforeseen reason " +
TOSTRING(result));
360 context->ClearExceptionCallback();
367 asIScriptFunction* scriptFunc = this->
engine->GetFunctionById(asFunctionID);
370 SLOG(
fmt::format(
"Cannot execute script function with ID {} - not found", asFunctionID));
374 int result = this->
context->Prepare(scriptFunc);
377 SLOG(
fmt::format(
"Cannot execute script function '{}': `AngelScript::Context::Prepare()` reported error code {}",
378 scriptFunc->GetName(), result));
406 std::vector<String> tmpQueue;
408 std::vector<String>::iterator it;
409 for (it=tmpQueue.begin(); it!=tmpQueue.end();it++)
440 AngelScript::asIScriptFunction* func =
m_script_units[id].scriptModule->GetFunctionByDecl(
441 "void fireEvent(string, float)");
446 context->SetArgObject(0, &instanceName);
447 context->SetArgFloat (1, intensity);
452 if ( r == AngelScript::asEXECUTION_FINISHED )
455 AngelScript::asDWORD ret =
context->GetReturnDWord();
474 int functionId = _functionId;
475 if (functionId <= 0 && (
m_script_units[
id].defaultEventCallbackFunctionPtr !=
nullptr))
478 functionId =
m_script_units[id].defaultEventCallbackFunctionPtr->GetId();
484 context->SetArgDWord (0, type);
488 context->SetArgDWord (3,
static_cast<AngelScript::asDWORD
>(nodenum));
490 context->SetArgDWord (3,
static_cast<AngelScript::asDWORD
>(-1));
505 AngelScript::asIScriptModule* mod =
nullptr;
510 result = ExecuteString(
engine, command.c_str(), mod,
context);
513 SLOG(
fmt::format(
"Error {} while executing string `{}`", result, command));
522 AngelScript::asIScriptModule* mod =
nullptr;
526 AngelScript::asIScriptFunction* func =
nullptr;
527 result = mod->CompileFunction(
"addfunc", arg.c_str(), 0, AngelScript::asCOMP_ADD_TO_MODULE, &func);
532 if (func == mod->GetFunctionByDecl(
"void frameStep(float)"))
537 else if (func == mod->GetFunctionByDecl(
"void eventCallback(int, int)"))
542 else if (func == mod->GetFunctionByDecl(
"void eventCallbackEx(scriptEvents, int, int, int, int, string, string, string, string)"))
558 SLOG(
fmt::format(
"Error {} adding function `{}` to script module '{}'", result, arg, mod->GetName()));
571 AngelScript::asIScriptModule* mod =
nullptr;
575 if (mod->GetFunctionByDecl(arg.c_str()) !=
nullptr)
584 AngelScript::asIScriptModule* mod =
nullptr;
588 AngelScript::asIScriptFunction* func = mod->GetFunctionByDecl(arg.c_str());
592 result = mod->RemoveFunction(func);
595 SLOG(
fmt::format(
"Error {} removing function `{}` from module '{}' - continuing anyway (compatibility).", result, arg, mod->GetName()));
618 SLOG(
fmt::format(
"Could not remove function `{}` from module '{}' - not found.", arg, mod->GetName()));
627 AngelScript::asIScriptModule* mod =
nullptr;
631 result = mod->CompileGlobalVar(
"addvar", arg.c_str(), 0);
634 SLOG(
fmt::format(
"Error {} while adding variable `{}` to module '{}'", result, arg, mod->GetName()));
643 AngelScript::asIScriptModule* mod =
nullptr;
647 result = mod->GetGlobalVarIndexByName(arg.c_str());
659 AngelScript::asIScriptModule* mod =
nullptr;
663 result = mod->GetGlobalVarIndexByName(arg.c_str());
666 result = mod->RemoveGlobalVar(result);
671 SLOG(
fmt::format(
"Error {} while removing variable `{}` from module '{}'", result, arg, mod->GetName()));
678 AngelScript::asIScriptModule* mod =
nullptr;
683 int index = mod->GetGlobalVarIndexByName(varName.c_str());
689 const char* asVarName =
nullptr;
690 const char* asNamespace =
nullptr;
692 bool asConst =
false;
693 int getResult = mod->GetGlobalVar(index, &asVarName, &asNamespace, &asTypeId, &asConst);
699 LOG(
fmt::format(
"[RoR|Scripting] getScriptVariable() - '{}' global var info: name='{}', namespace='{}', typeid={}, const={}",
700 varName, asVarName, asNamespace, asTypeId, asConst));
704 if( refTypeId & asTYPEID_OBJHANDLE )
710 if( (asTypeId & asTYPEID_MASK_OBJECT) )
713 if( (asTypeId & asTYPEID_HANDLETOCONST) && !(refTypeId & asTYPEID_HANDLETOCONST) )
715 SLOG(
fmt::format(
"Error in `getScriptVariable()` - '{}' is a handle to `const` object but the requested type is not.", varName));
720 engine->RefCastObject(mod->GetAddressOfGlobalVar(index),
engine->GetTypeInfoById(asTypeId),
engine->GetTypeInfoById(refTypeId),
reinterpret_cast<void**
>(ref));
721 if( *(asPWORD*)ref == 0 )
723 SLOG(
fmt::format(
"Error in `getScriptVariable()` - '{}': reference-cast from '{}' to '{}' yielded null",
724 varName,
engine->GetTypeDeclaration(asTypeId),
engine->GetTypeDeclaration(refTypeId)));
730 else if( refTypeId & asTYPEID_MASK_OBJECT )
735 if( asTypeId == refTypeId )
737 engine->AssignScriptObject(ref, mod->GetAddressOfGlobalVar(index),
engine->GetTypeInfoById(asTypeId));
746 if( asTypeId == refTypeId )
748 int size =
engine->GetSizeOfPrimitiveType(refTypeId);
749 memcpy(ref, mod->GetAddressOfGlobalVar(index), size);
754 SLOG(
fmt::format(
"Error in `getScriptVariable()` - '{}' has incompatible type, expected '{}' (typeid {}), got '{}' (typeid {})",
755 varName,
engine->GetTypeDeclaration(refTypeId), refTypeId,
engine->GetTypeDeclaration(asTypeId), asTypeId));
761 std::string decl =
fmt::format(fmtFuncDecl, funcName);
762 asIScriptFunction* retval =
m_script_units[nid].scriptModule->GetFunctionByDecl(decl.c_str());
765 asIScriptFunction* candidate =
m_script_units[nid].scriptModule->GetFunctionByName(funcName.c_str());
768 SLOG(
fmt::format(
"Warning: a callback function with signature '{}' was not found"
769 " but a function with given name exists: '{}' - did you make a typo in arguments?",
770 decl, candidate->GetDeclaration()));
774 SLOG(
fmt::format(
"Warning: a callback function with signature '{}' was not found",
788 asIScriptFunction* callback =
m_script_units[id].eventCallbackExFunctionPtr;
801 context->SetArgDWord(0, eventnum);
806 context->SetArgDWord(2, arg2ex);
807 context->SetArgDWord(3, arg3ex);
808 context->SetArgDWord(4, arg4ex);
809 context->SetArgObject(5, &arg5ex);
810 context->SetArgObject(6, &arg6ex);
811 context->SetArgObject(7, &arg7ex);
812 context->SetArgObject(8, &arg8ex);
830 ActorPtr associatedActor , std::string buffer )
891 result = builder.StartNewModule(
engine, moduleName.c_str());
895 fmt::format(
"Could not load script '{}' - failed to create module.", moduleName));
898 m_script_units[unit_id].scriptModule =
engine->GetModule(moduleName.c_str(), AngelScript::asGM_ONLY_IF_EXISTS);
907 fmt::format(
"Could not load script '{}' - failed to create global variable `thisActor`.", moduleName));
914 fmt::format(
"const int thisScript = {};", unit_id).c_str());
918 fmt::format(
"Could not load script '{}' - failed to create global variable `thisScript`.", moduleName));
929 fmt::format(
"Could not load script '{}' from buffer", moduleName));
936 result = builder.AddSectionFromFile(
m_script_units[unit_id].scriptName.c_str());
940 fmt::format(
"Could not load script '{}' - failed to process file.", moduleName));
950 result = builder.BuildModule();
955 fmt::format(
"Could not load script '{}' - failed to build module. See 'Angelscript.log' for more info.", moduleName));
961 scriptHash = builder.
GetHash();
966 m_script_units[unit_id].eventCallbackFunctionPtr =
m_script_units[unit_id].scriptModule->GetFunctionByDecl(
"void eventCallback(int, int)");
967 m_script_units[unit_id].eventCallbackExFunctionPtr =
m_script_units[unit_id].scriptModule->GetFunctionByDecl(
"void eventCallbackEx(scriptEvents, int, int, int, int, string, string, string, string)");
974 auto main_func =
m_script_units[unit_id].scriptModule->GetFunctionByDecl(
"void main()");
975 if ( main_func ==
nullptr )
986 result =
context->Prepare(main_func);
990 fmt::format(
"Could not load script '{}' - failed to build module.", moduleName));
998 int var_index =
m_script_units[unit_id].scriptModule->GetGlobalVarIndexByName(
"thisActor");
1001 SLOG(
"Could not find global var `thisActor`");
1007 if (thisActorAddr ==
nullptr)
1009 SLOG(
"Could not retrieve address of global var `thisActor`");
1012 *thisActorAddr =
m_script_units[unit_id].associatedActor.GetRef();
1013 (*thisActorAddr)->AddRef();
1018 SLOG(
fmt::format(
"Executing main() in {}", moduleName));
1020 if ( mainfunc_result != AngelScript::asEXECUTION_FINISHED )
1023 fmt::format(
"Could not load script '{}' - error running function `main()`, check AngelScript.log", moduleName));
1027 SLOG(
"The script finished successfully.");
1030 return mainfunc_result;