#ifndef PKMNLIB_ANGELSCRIPTRESOLVER_HPP #define PKMNLIB_ANGELSCRIPTRESOLVER_HPP #include #include #ifdef ANGELSCRIPT_DEBUGGER #include #endif #include #include "../../Battling/Library/BattleLibrary.hpp" #include "AngelScriptEvolutionScript.hpp" #define ANGELSCRIPT_DLL_LIBRARY_IMPORT #include #include #include "../../Battling/PkmnScriptCategory.hpp" #include "AngelScriptItemUseScript.hpp" #include "AngelScriptScript.hpp" #include "AngelScriptTypeInfo.hpp" class AngelscriptUserdata; class AngelScriptResolver final : public PkmnLib::Battling::ScriptResolver { private: asIScriptEngine* _engine = nullptr; asIScriptModule* _mainModule = nullptr; ContextPool* _contextPool = nullptr; CScriptBuilder _builder = {}; std::string _sourceDirectory = {}; AngelscriptUserdata* _userData; #ifdef ANGELSCRIPT_DEBUGGER ArbUt::OptionalUniquePtr _debugger; #endif ArbUt::Dictionary> _typeDatabase; ArbUt::Dictionary _baseTypes; std::mutex _baseTypesLock; ArbUt::Dictionary _itemUseTypes; ArbUt::Dictionary _evolutionTypes; ArbUt::Dictionary _itemUseScripts; ArbUt::Dictionary _evolutionScripts; ArbUt::Dictionary _scriptOwnerTypes; static void MessageCallback(const asSMessageInfo* msg, void* param); static void Print(const std::string& str) { std::cout << str << std::endl; } static void PrintConst(const ArbUt::StringView& str) { Print(std::string(str.std_str())); } static i32 IncludeCallback(const char* include, const char* from, CScriptBuilder* builder, void* userParam); void RegisterTypes(); void InitializeByteCode(const ArbUt::Dictionary>& types); void RegisterScriptType(asITypeInfo* typeInfo, const ArbUt::StringView& metadataKind, const ArbUt::StringView& effectName); public: AngelScriptResolver(); ~AngelScriptResolver() override; void Initialize(CreatureLib::Battling::BattleLibrary* library) override { Initialize(library, true); } void Initialize(CreatureLib::Battling::BattleLibrary* library, bool includeStandard); void CreateScript(const char* name, const char* script); inline void SetSourceDirectory(std::string const& path) noexcept { _sourceDirectory = path; } const asIScriptModule* GetMainModule() const noexcept { return _mainModule; } CScriptBuilder& GetBuilder() noexcept { return _builder; } void FinalizeModule(); void DefineWord(const std::string& word) { _builder.DefineWord(word.c_str()); } CreatureLib::Battling::BattleScript* LoadScript(const ArbUt::OptionalBorrowedPtr& owner, ScriptCategory category, const ArbUt::StringView& scriptName) override; CreatureLib::Battling::ItemUseScript* LoadItemScript(const CreatureLib::Library::Item* item) override; ArbUt::OptionalBorrowedPtr LoadEvolutionScript(const ArbUt::StringView& view) override; void WriteByteCodeToFile(const char* file, bool stripDebugInfo = false); void LoadByteCodeFromFile(const char* file); uint8_t* WriteByteCodeToMemory(size_t& size, bool stripDebugInfo = false); void LoadByteCodeFromMemory(uint8_t*, size_t size); const ArbUt::Dictionary>& GetTypeDatabase() const noexcept { return _typeDatabase; } void RegisterType(const char* type) { int r = _engine->RegisterObjectType(type, 0, asOBJ_REF | asOBJ_NOCOUNT); Ensure(r >= 0); } void RegisterTypeMethod(const char* type, const char* decl, void*(func)(void*)) { int r = _engine->RegisterObjectMethod(type, decl, asFunctionPtr(func), asCALL_CDECL_OBJFIRST); Ensure(r >= 0); } void RegisterGlobalMethod(const char*, void*(func)(void*)) { auto r = _engine->RegisterGlobalFunction("decl", asFunctionPtr(func), asCALL_CDECL); Ensure(r >= 0); } asITypeInfo* GetBaseType(const ArbUt::StringView& name) { asITypeInfo* t; auto lock = std::lock_guard(_baseTypesLock); auto v = _baseTypes.TryGet(name); if (!v.has_value()) { t = _mainModule->GetTypeInfoByName(name.c_str()); if (t == NULL) { t = _engine->GetTypeInfoByDecl(name.c_str()); } _baseTypes.Insert(name, t); } else { t = v.value(); } return t; } inline ContextPool* GetContextPool() const noexcept { return _contextPool; } inline asIScriptEngine* GetEngine() const noexcept { return _engine; } inline AngelscriptUserdata* GetUserdata() const noexcept { return _userData; } #ifdef ANGELSCRIPT_DEBUGGER inline ArbUt::OptionalBorrowedPtr GetDebugger() const noexcept { return _debugger.GetValue(); } inline void SetDebugger(AngelscriptDebugger* debugger) noexcept { _debugger = debugger; } #endif asITypeInfo* GetScriptOwnerType(ScriptCategory category) { auto tryget = _scriptOwnerTypes.TryGet(category); if (tryget.has_value()) { return tryget.value(); } asITypeInfo* t = nullptr; switch (category) { case ScriptCategory::Attack: t = _engine->GetTypeInfoByName("ExecutingMove"); break; case ScriptCategory::Talent: t = _engine->GetTypeInfoByName("Pokemon"); break; case ScriptCategory::Status: t = _engine->GetTypeInfoByName("Pokemon"); break; case ScriptCategory::Creature: t = _engine->GetTypeInfoByName("Pokemon"); break; case ScriptCategory::Battle: t = _engine->GetTypeInfoByName("Battle"); break; case ScriptCategory::Side: t = _engine->GetTypeInfoByName("BattleSide"); break; case ScriptCategory::ItemBattleTrigger: t = _engine->GetTypeInfoByName("Pokemon"); break; } switch (static_cast(category)) { case PkmnScriptCategory::Weather: t = _engine->GetTypeInfoByName("Battle"); break; } _scriptOwnerTypes.Set(category, t); return t; } void Reset(CreatureLib::Battling::BattleLibrary* library); }; #endif // PKMNLIB_ANGELSCRIPRESOLVER_HPP