/* * Update: 2024-3-2 22:11 * Source: https://github.com/issuimo/UnityResolve.hpp * Author: github@issuimo */ #ifndef UNITYRESOLVE_HPP #define UNITYRESOLVE_HPP #define WINDOWS_MODE 0 // 如果需要请改为 1 | 1 if you need #define ANDROID_MODE 1 #define LINUX_MODE 0 /* Never * #define MAC_MODE 0 * #define IOS_MODE 0 */ #if WINDOWS_MODE || LINUX_MODE #include #endif #include #include #include #include //#include #include #include #include #include #if WINDOWS_MODE #include #undef GetObject #endif #if WINDOWS_MODE #ifdef _WIN64 #define UNITY_CALLING_CONVENTION __fastcall #elif _WIN32 #define UNITY_CALLING_CONVENTION __cdecl #endif #elif ANDROID_MODE || LINUX_MODE #include // #include #define UNITY_CALLING_CONVENTION #endif #include "xdl.h" #include "../../GakumasLocalify/Log.h" #include "../../GakumasLocalify/Misc.hpp" class UnityResolveProgress final { public: struct Progress { long current = 0; long total = 1; }; static bool startInit; static Progress assembliesProgress; static Progress classProgress; }; class UnityResolve final { public: struct Assembly; struct Type; struct Class; struct Field; struct Method; class UnityType; enum class Mode : char { Il2Cpp, Mono, }; struct Assembly final { void* address; std::string name; std::string file; std::vector classes; [[nodiscard]] auto Get(const std::string& strClass, const std::string& strNamespace = "*", const std::string& strParent = "*") const -> Class* { if (!this) return nullptr; /* if (lazyInit_ && classes.empty()) { const auto image = Invoke("il2cpp_assembly_get_image", address); ForeachClass(const_cast(this), image); }*/ for (const auto pClass : classes) if (strClass == pClass->name && (strNamespace == "*" || pClass->namespaze == strNamespace) && (strParent == "*" || pClass->parent == strParent)) return pClass; if (lazyInit_) { return FillClass_Il2ccpp(const_cast(this), strNamespace.c_str(), strClass.c_str()); } return nullptr; } }; struct Type final { void* address; std::string name; int size; // UnityType::CsType* [[nodiscard]] auto GetCSType() const -> void* { if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_type_get_object", address); return Invoke("mono_type_get_object", pDomain, address); } }; struct Class final { void* address; std::string name; std::string parent; std::string namespaze; std::vector fields; std::vector methods; void* objType; template auto Get(const std::string& name, const std::vector& args = {}) -> RType* { if (!this) return nullptr; if constexpr (std::is_same_v) for (auto pField : fields) if (pField->name == name) return static_cast(pField); if constexpr (std::is_same_v) for (const auto pField : fields) if (pField->name == name) return reinterpret_cast(pField->offset); if constexpr (std::is_same_v) { for (auto pMethod : methods) { if (pMethod->name == name) { if (pMethod->args.empty() && args.empty()) return static_cast(pMethod); if (pMethod->args.size() == args.size()) { size_t index{ 0 }; for (size_t i{ 0 }; const auto & typeName : args) if (typeName == "*" || typeName.empty() ? true : pMethod->args[i++]->pType->name == typeName) index++; if (index == pMethod->args.size()) return static_cast(pMethod); } } } for (auto pMethod : methods) if (pMethod->name == name) return static_cast(pMethod); } return nullptr; } template auto GetValue(void* obj, const std::string& name) -> RType { return *reinterpret_cast(reinterpret_cast(obj) + Get(name)->offset); } template auto SetValue(void* obj, const std::string& name, RType value) -> void { return *reinterpret_cast(reinterpret_cast(obj) + Get(name)->offset) = value; } // UnityType::CsType* [[nodiscard]] auto GetType() -> void* { if (objType) return objType; if (mode_ == Mode::Il2Cpp) { const auto pUType = Invoke("il2cpp_class_get_type", address); objType = Invoke("il2cpp_type_get_object", pUType); return objType; } const auto pUType = Invoke("mono_class_get_type", address); objType = Invoke("mono_type_get_object", pDomain, pUType); return objType; } /** * \brief 获取类所有实例 * \tparam T 返回数组类型 * \param type 类 * \return 返回实例指针数组 */ template auto FindObjectsByType() -> std::vector { static Method* pMethod; if (!pMethod) pMethod = UnityResolve::Get("UnityEngine.CoreModule.dll")->Get("Object")->Get(mode_ == Mode::Il2Cpp ? "FindObjectsOfType" : "FindObjectsOfTypeAll", { "System.Type" }); if (!objType) objType = this->GetType(); if (pMethod && objType) if (auto array = pMethod->Invoke*>(objType)) return array->ToVector(); return std::vector(0); } template auto New() -> T* { if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_object_new", address); return Invoke("mono_object_new", pDomain, address); } }; struct Field final { void* address; std::string name; Type* type; Class* klass; std::int32_t offset; // If offset is -1, then it's thread static bool static_field; void* vTable; template auto SetValue(T* value) const -> void { if (!static_field) return; if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_field_static_set_value", address, value); } template auto GetValue(T* value) const -> void { if (!static_field) return; if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_field_static_get_value", address, value); } }; struct Method final { void* address; std::string name; Class* klass; Type* return_type; std::int32_t flags; bool static_function; void* function; struct Arg { std::string name; Type* pType; }; std::vector args; private: bool badPtr{ false }; public: template auto Invoke(Args... args) -> Return { if (!this) return Return(); Compile(); #if WINDOWS_MODE try { if (!badPtr) badPtr = !IsBadCodePtr(reinterpret_cast(function)); if (function && badPtr) return reinterpret_cast(function)(args...); } catch (...) { std::cout << name << " Invoke Error\n"; } #else try { if (function) return reinterpret_cast(function)(args...); } catch (...) { std::cout << name << " Invoke Error\n"; } #endif return Return(); } auto Compile() -> void { if (!this) return; if (address && !function && mode_ == Mode::Mono) function = UnityResolve::Invoke("mono_compile_method", address); } template auto RuntimeInvoke(Obj* obj, Args... args) -> Return { if (!this) return Return(); void* exc{}; void* argArray[sizeof...(Args) + 1]; if (sizeof...(Args) > 0) { size_t index = 0; ((argArray[index++] = static_cast(&args)), ...); } if (mode_ == Mode::Il2Cpp) { if constexpr (std::is_void_v) { UnityResolve::Invoke("il2cpp_runtime_invoke", address, obj, argArray, exc); return; } else return *static_cast(UnityResolve::Invoke("il2cpp_runtime_invoke", address, obj, argArray, exc)); } if constexpr (std::is_void_v) { UnityResolve::Invoke("mono_runtime_invoke", address, obj, argArray, exc); return; } else return *static_cast(UnityResolve::Invoke("mono_runtime_invoke", address, obj, argArray, exc)); return Return(); } template using MethodPointer = Return(UNITY_CALLING_CONVENTION*)(Args...); template auto Cast() -> MethodPointer { if (!this) return nullptr; Compile(); if (function) return reinterpret_cast>(function); return nullptr; } }; static auto ThreadAttach() -> void { if (mode_ == Mode::Il2Cpp) Invoke("il2cpp_thread_attach", pDomain); else { Invoke("mono_thread_attach", pDomain); Invoke("mono_jit_thread_attach", pDomain); } } static auto ThreadDetach() -> void { if (mode_ == Mode::Il2Cpp) Invoke("il2cpp_thread_detach", pDomain); else { Invoke("mono_thread_detach", pDomain); Invoke("mono_jit_thread_detach", pDomain); } } static auto Init(void* hmodule, const Mode mode = Mode::Mono, const bool lazyInit = false) -> void { mode_ = mode; hmodule_ = hmodule; lazyInit_ = lazyInit; if (mode_ == Mode::Il2Cpp) { if (!lazyInit) UnityResolveProgress::startInit = true; pDomain = Invoke("il2cpp_domain_get"); Invoke("il2cpp_thread_attach", pDomain); ForeachAssembly(); if (!lazyInit) UnityResolveProgress::startInit = false; } else { pDomain = Invoke("mono_get_root_domain"); Invoke("mono_thread_attach", pDomain); Invoke("mono_jit_thread_attach", pDomain); ForeachAssembly(); if (Get("UnityEngine.dll") && (!Get("UnityEngine.CoreModule.dll") || !Get("UnityEngine.PhysicsModule.dll"))) { // 兼容某些游戏 (如生死狙击2) for (const std::vector names = { "UnityEngine.CoreModule.dll", "UnityEngine.PhysicsModule.dll" }; const auto name : names) { const auto ass = Get("UnityEngine.dll"); const auto assembly = new Assembly{ .address = ass->address, .name = name, .file = ass->file, .classes = ass->classes }; UnityResolve::assembly.push_back(assembly); } } } } #if WINDOWS_MODE || LINUX_MODE /*__cplusplus >= 202002L*/ static auto DumpToFile(const std::string& path) -> void { std::ofstream io(path + "dump.cs", std::fstream::out); if (!io) return; for (const auto& pAssembly : assembly) { for (const auto& pClass : pAssembly->classes) { io << std::format("\tnamespace: {}", pClass->namespaze.empty() ? "" : pClass->namespaze); io << "\n"; io << std::format("\tAssembly: {}\n", pAssembly->name.empty() ? "" : pAssembly->name); io << std::format("\tAssemblyFile: {} \n", pAssembly->file.empty() ? "" : pAssembly->file); io << std::format("\tclass {}{} ", pClass->name, pClass->parent.empty() ? "" : " : " + pClass->parent); io << "{\n\n"; for (const auto& pField : pClass->fields) io << std::format("\t\t{:+#06X} | {}{} {};\n", pField->offset, pField->static_field ? "static " : "", pField->type->name, pField->name); io << "\n"; for (const auto& pMethod : pClass->methods) { io << std::format("\t\t[Flags: {:032b}] [ParamsCount: {:04d}] |RVA: {:+#010X}|\n", pMethod->flags, pMethod->args.size(), reinterpret_cast(pMethod->function) - reinterpret_cast(hmodule_)); io << std::format("\t\t{}{} {}(", pMethod->static_function ? "static " : "", pMethod->return_type->name, pMethod->name); std::string params{}; for (const auto& pArg : pMethod->args) params += std::format("{} {}, ", pArg->pType->name, pArg->name); if (!params.empty()) { params.pop_back(); params.pop_back(); } io << (params.empty() ? "" : params) << ");\n\n"; } io << "\t}\n\n"; } } io << '\n'; io.close(); std::ofstream io2(path + "struct.hpp", std::fstream::out); if (!io2) return; for (const auto& pAssembly : assembly) { for (const auto& pClass : pAssembly->classes) { io2 << std::format("\tnamespace: {}", pClass->namespaze.empty() ? "" : pClass->namespaze); io2 << "\n"; io2 << std::format("\tAssembly: {}\n", pAssembly->name.empty() ? "" : pAssembly->name); io2 << std::format("\tAssemblyFile: {} \n", pAssembly->file.empty() ? "" : pAssembly->file); io2 << std::format("\tstruct {}{} ", pClass->name, pClass->parent.empty() ? "" : " : " + pClass->parent); io2 << "{\n\n"; for (size_t i = 0; i < pClass->fields.size(); i++) { if (pClass->fields[i]->static_field) continue; auto field = pClass->fields[i]; next: if ((i + 1) >= pClass->fields.size()) { io2 << std::format("\t\tchar {}[0x{:06X}];\n", field->name, 0x4); continue; } if (pClass->fields[i + 1]->static_field) { i++; goto next; } std::string name = field->name; std::ranges::replace(name, '<', '_'); std::ranges::replace(name, '>', '_'); if (field->type->name == "System.Int64") { io2 << std::format("\t\tstd::int64_t {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 8) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 8); continue; } if (field->type->name == "System.UInt64") { io2 << std::format("\t\tstd::uint64_t {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 8) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 8); continue; } if (field->type->name == "System.Int32") { io2 << std::format("\t\tint {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 4) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 4); continue; } if (field->type->name == "System.UInt32") { io2 << std::format("\t\tstd::uint32_t {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 4) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 4); continue; } if (field->type->name == "System.Boolean") { io2 << std::format("\t\tbool {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 1) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 1); continue; } if (field->type->name == "System.String") { io2 << std::format("\t\tUnityResolve::UnityType::String* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } if (field->type->name == "System.Single") { io2 << std::format("\t\tfloat {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 4) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 4); continue; } if (field->type->name == "System.Double") { io2 << std::format("\t\tdouble {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > 8) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - 8); continue; } if (field->type->name == "UnityEngine.Vector3") { io2 << std::format("\t\tUnityResolve::UnityType::Vector3 {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Vector3)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Vector3)); continue; } if (field->type->name == "UnityEngine.Vector2") { io2 << std::format("\t\tUnityResolve::UnityType::Vector2 {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Vector2)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Vector2)); continue; } if (field->type->name == "UnityEngine.Vector4") { io2 << std::format("\t\tUnityResolve::UnityType::Vector4 {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Vector4)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Vector4)); continue; } if (field->type->name == "UnityEngine.GameObject") { io2 << std::format("\t\tUnityResolve::UnityType::GameObject* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } if (field->type->name == "UnityEngine.Transform") { io2 << std::format("\t\tUnityResolve::UnityType::Transform* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } if (field->type->name == "UnityEngine.Animator") { io2 << std::format("\t\tUnityResolve::UnityType::Animator* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } if (field->type->name == "UnityEngine.Physics") { io2 << std::format("\t\tUnityResolve::UnityType::Physics* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } if (field->type->name == "UnityEngine.Component") { io2 << std::format("\t\tUnityResolve::UnityType::Component* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } if (field->type->name == "UnityEngine.Rect") { io2 << std::format("\t\tUnityResolve::UnityType::Rect {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Rect)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Rect)); continue; } if (field->type->name == "UnityEngine.Quaternion") { io2 << std::format("\t\tUnityResolve::UnityType::Quaternion {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Quaternion)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Quaternion)); continue; } if (field->type->name == "UnityEngine.Color") { io2 << std::format("\t\tUnityResolve::UnityType::Color {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Color)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Color)); continue; } if (field->type->name == "UnityEngine.Matrix4x4") { io2 << std::format("\t\tUnityResolve::UnityType::Matrix4x4 {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(UnityType::Matrix4x4)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(UnityType::Matrix4x4)); continue; } if (field->type->name == "UnityEngine.Rigidbody") { io2 << std::format("\t\tUnityResolve::UnityType::Rigidbody* {};\n", name); if (!pClass->fields[i + 1]->static_field && (pClass->fields[i + 1]->offset - field->offset) > sizeof(void*)) io2 << std::format("\t\tchar {}_[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset - sizeof(void*)); continue; } io2 << std::format("\t\tchar {}[0x{:06X}];\n", name, pClass->fields[i + 1]->offset - field->offset); } io2 << "\n"; io2 << "\t};\n\n"; } } io2 << '\n'; io2.close(); } #endif /** * \brief 调用dll函数 * \tparam Return 返回类型 (必须) * \tparam Args 参数类型 (可以忽略) * \param funcName dll导出函数名称 * \param args 参数 * \return 模板类型 */ template static auto Invoke(const std::string& funcName, Args... args) -> Return { static std::mutex mutex{}; std::lock_guard lock(mutex); // 检查函数是否已经获取地址, 没有则自动获取 #if WINDOWS_MODE if (!address_.contains(funcName) || !address_[funcName]) address_[funcName] = static_cast(GetProcAddress(static_cast(hmodule_), funcName.c_str())); #elif ANDROID_MODE || LINUX_MODE if (address_.find(funcName) == address_.end() || !address_[funcName]) { auto xdlAddr = xdl_sym(hmodule_, funcName.c_str(), NULL); if (!xdlAddr) { address_[funcName] = dlsym(hmodule_, funcName.c_str()); } else { address_[funcName] = xdlAddr; } } #endif if (address_[funcName] != nullptr) { try { return reinterpret_cast(address_[funcName])(args...); } catch (...) { std::cout << funcName << " Invoke Error\n"; Return(); } } Return(); } inline static std::vector assembly; static auto Get(const std::string& strAssembly) -> Assembly* { for (const auto pAssembly : assembly) if (pAssembly->name == strAssembly) return pAssembly; return nullptr; } private: static auto ForeachAssembly() -> void { // 遍历程序集 if (mode_ == Mode::Il2Cpp) { size_t nrofassemblies = 0; const auto assemblies = Invoke("il2cpp_domain_get_assemblies", pDomain, &nrofassemblies); if (!lazyInit_) UnityResolveProgress::assembliesProgress.total = nrofassemblies; for (auto i = 0; i < nrofassemblies; i++) { if (!lazyInit_) UnityResolveProgress::assembliesProgress.current = i + 1; const auto ptr = assemblies[i]; if (ptr == nullptr) continue; auto assembly = new Assembly{ .address = ptr }; const auto image = Invoke("il2cpp_assembly_get_image", ptr); assembly->file = Invoke("il2cpp_image_get_filename", image); assembly->name = Invoke("il2cpp_image_get_name", image); UnityResolve::assembly.push_back(assembly); if (!lazyInit_) { ForeachClass(assembly, image); } } } else { Invoke&), std::vector&>("mono_assembly_foreach", [](void* ptr, std::vector& v) { if (ptr == nullptr) return; const auto assembly = new Assembly{ .address = ptr, }; const auto image = Invoke("mono_assembly_get_image", ptr); assembly->file = Invoke("mono_image_get_filename", image); assembly->name = Invoke("mono_image_get_name", image); assembly->name += ".dll"; v.push_back(assembly); ForeachClass(assembly, image); }, assembly); } } static auto GetPClassFromUnknownNamespace(void* image, const char* klassName) -> void* { const auto count = Invoke("il2cpp_image_get_class_count", image); for (auto i = 0; i < count; i++) { const auto pClass = Invoke("il2cpp_image_get_class", image, i); const auto className = Invoke("il2cpp_class_get_name", pClass); if (strcmp(className, klassName) == 0) { return pClass; } } return nullptr; } static auto FillClass_Il2ccpp(Assembly* assembly, const char* namespaze, const char* klassName) -> Class* { auto image = Invoke("il2cpp_assembly_get_image", assembly->address); void* pClass; if (strcmp(namespaze, "*") == 0) { pClass = GetPClassFromUnknownNamespace(image, klassName); } else { pClass = Invoke("il2cpp_class_from_name", image, namespaze, klassName); } if (!pClass && (strlen(namespaze) == 0)) { pClass = GetPClassFromUnknownNamespace(image, klassName); } if (pClass == nullptr) return nullptr; const auto pAClass = new Class(); pAClass->address = pClass; pAClass->name = Invoke("il2cpp_class_get_name", pClass); if (const auto pPClass = Invoke("il2cpp_class_get_parent", pClass)) pAClass->parent = Invoke("il2cpp_class_get_name", pPClass); // pAClass->namespaze = Invoke("il2cpp_class_get_namespace", pClass); pAClass->namespaze = namespaze; assembly->classes.push_back(pAClass); ForeachFields(pAClass, pClass); ForeachMethod(pAClass, pClass); void* i_class{}; void* iter{}; do { if ((i_class = Invoke("il2cpp_class_get_interfaces", pClass, &iter))) { ForeachFields(pAClass, i_class); ForeachMethod(pAClass, i_class); } } while (i_class); return pAClass; } static auto ForeachClass(Assembly* assembly, void* image) -> void { // 遍历类 if (mode_ == Mode::Il2Cpp) { const auto count = Invoke("il2cpp_image_get_class_count", image); if (!lazyInit_) UnityResolveProgress::classProgress.total = count; for (auto i = 0; i < count; i++) { if (!lazyInit_) UnityResolveProgress::classProgress.current = i + 1; const auto pClass = Invoke("il2cpp_image_get_class", image, i); if (pClass == nullptr) continue; const auto pAClass = new Class(); pAClass->address = pClass; pAClass->name = Invoke("il2cpp_class_get_name", pClass); if (const auto pPClass = Invoke("il2cpp_class_get_parent", pClass)) pAClass->parent = Invoke("il2cpp_class_get_name", pPClass); pAClass->namespaze = Invoke("il2cpp_class_get_namespace", pClass); assembly->classes.push_back(pAClass); ForeachFields(pAClass, pClass); ForeachMethod(pAClass, pClass); void* i_class{}; void* iter{}; do { if ((i_class = Invoke("il2cpp_class_get_interfaces", pClass, &iter))) { ForeachFields(pAClass, i_class); ForeachMethod(pAClass, i_class); } } while (i_class); } } else { const void* table = Invoke("mono_image_get_table_info", image, 2); const auto count = Invoke("mono_table_info_get_rows", table); for (auto i = 0; i < count; i++) { const auto pClass = Invoke("mono_class_get", image, 0x02000000 | (i + 1)); if (pClass == nullptr) continue; const auto pAClass = new Class(); pAClass->address = pClass; pAClass->name = Invoke("mono_class_get_name", pClass); if (const auto pPClass = Invoke("mono_class_get_parent", pClass)) pAClass->parent = Invoke("mono_class_get_name", pPClass); pAClass->namespaze = Invoke("mono_class_get_namespace", pClass); assembly->classes.push_back(pAClass); ForeachFields(pAClass, pClass); ForeachMethod(pAClass, pClass); void* iClass{}; void* iiter{}; do { if ((iClass = Invoke("mono_class_get_interfaces", pClass, &iiter))) { ForeachFields(pAClass, iClass); ForeachMethod(pAClass, iClass); } } while (iClass); } } } static auto ForeachFields(Class* klass, void* pKlass) -> void { // 遍历成员 if (mode_ == Mode::Il2Cpp) { void* iter = nullptr; void* field; do { if ((field = Invoke("il2cpp_class_get_fields", pKlass, &iter))) { const auto pField = new Field{ .address = field, .name = Invoke("il2cpp_field_get_name", field), .type = new Type{.address = Invoke("il2cpp_field_get_type", field)}, .klass = klass, .offset = Invoke("il2cpp_field_get_offset", field), .static_field = false, .vTable = nullptr }; int tSize{}; pField->static_field = pField->offset <= 0; pField->type->name = Invoke("il2cpp_type_get_name", pField->type->address); pField->type->size = -1; klass->fields.push_back(pField); } } while (field); } else { void* iter = nullptr; void* field; do { if ((field = Invoke("mono_class_get_fields", pKlass, &iter))) { const auto pField = new Field{ .address = field, .name = Invoke("mono_field_get_name", field), .type = new Type{.address = Invoke("mono_field_get_type", field)}, .klass = klass, .offset = Invoke("mono_field_get_offset", field), .static_field = false, .vTable = nullptr }; int tSize{}; pField->static_field = pField->offset <= 0; pField->type->name = Invoke("mono_type_get_name", pField->type->address); pField->type->size = Invoke("mono_type_size", pField->type->address, &tSize); klass->fields.push_back(pField); } } while (field); } } static auto ForeachMethod(Class* klass, void* pKlass) -> void { // 遍历方法 if (mode_ == Mode::Il2Cpp) { void* iter = nullptr; void* method; do { if ((method = Invoke("il2cpp_class_get_methods", pKlass, &iter))) { int fFlags{}; const auto pMethod = new Method{}; pMethod->address = method; pMethod->name = Invoke("il2cpp_method_get_name", method); pMethod->klass = klass; pMethod->return_type = new Type{ .address = Invoke("il2cpp_method_get_return_type", method), }; pMethod->flags = Invoke("il2cpp_method_get_flags", method, &fFlags); int tSize{}; pMethod->static_function = pMethod->flags & 0x10; pMethod->return_type->name = Invoke("il2cpp_type_get_name", pMethod->return_type->address); pMethod->return_type->size = -1; pMethod->function = *static_cast(method); klass->methods.push_back(pMethod); const auto argCount = Invoke("il2cpp_method_get_param_count", method); for (auto index = 0; index < argCount; index++) pMethod->args.push_back(new Method::Arg{ Invoke("il2cpp_method_get_param_name", method, index), new Type{.address = Invoke("il2cpp_method_get_param", method, index), .name = Invoke("il2cpp_type_get_name", Invoke("il2cpp_method_get_param", method, index)), .size = -1} }); } } while (method); } else { void* iter = nullptr; void* method; do { if ((method = Invoke("mono_class_get_methods", pKlass, &iter))) { const auto signature = Invoke("mono_method_signature", method); int fFlags{}; const auto pMethod = new Method{}; pMethod->address = method; pMethod->name = Invoke("mono_method_get_name", method); pMethod->klass = klass; pMethod->return_type = new Type{ .address = Invoke("mono_signature_get_return_type", method), }; pMethod->flags = Invoke("mono_method_get_flags", method, &fFlags); int tSize{}; pMethod->static_function = pMethod->flags & 0x10; pMethod->return_type->name = Invoke("mono_type_get_name", pMethod->return_type->address); pMethod->return_type->size = Invoke("mono_type_size", pMethod->return_type->address, &tSize); klass->methods.push_back(pMethod); const auto names = new char* [Invoke("mono_signature_get_param_count", signature)]; Invoke("mono_method_get_param_names", method, names); void* mIter = nullptr; void* mType; auto iname = 0; do { if ((mType = Invoke("mono_signature_get_params", signature, &mIter))) { int t_size{}; try { pMethod->args.push_back(new Method::Arg{ names[iname], new Type{.address = mType, .name = Invoke("mono_type_get_name", mType), .size = Invoke("mono_type_size", mType, &t_size)} }); } catch (...) { // USE SEH!!! } iname++; } } while (mType); } } while (method); } } public: class UnityType final { public: using IntPtr = std::uintptr_t; using Int32 = std::int32_t; using Int64 = std::int64_t; using Char = wchar_t; using Int16 = std::int16_t; using Byte = std::uint8_t; struct Vector3; struct Camera; struct Transform; struct Component; struct UnityObject; struct LayerMask; struct Rigidbody; struct Physics; struct Time; struct GameObject; struct Collider; struct Vector4; struct Vector2; struct Quaternion; struct Bounds; struct Plane; struct Ray; struct Rect; struct Color; struct Matrix4x4; template struct Array; struct String; struct Object; template struct List; template struct Dictionary; struct Behaviour; struct MonoBehaviour; struct CsType; struct Mesh; struct Renderer; struct Animator; struct CapsuleCollider; struct BoxCollider; struct Vector3 { float x, y, z; Vector3() { x = y = z = 0.f; } Vector3(const float f1, const float f2, const float f3) { x = f1; y = f2; z = f3; } [[nodiscard]] auto Length() const -> float { return x * x + y * y + z * z; } [[nodiscard]] auto Dot(const Vector3 b) const -> float { return x * b.x + y * b.y + z * b.z; } [[nodiscard]] auto Normalize() const -> Vector3 { if (const auto len = Length(); len > 0) return Vector3(x / len, y / len, z / len); return Vector3(x, y, z); } auto ToVectors(Vector3* m_pForward, Vector3* m_pRight, Vector3* m_pUp) const -> void { constexpr auto m_fDeg2Rad = static_cast(3.1415926) / 180.F; const auto m_fSinX = sinf(x * m_fDeg2Rad); const auto m_fCosX = cosf(x * m_fDeg2Rad); const auto m_fSinY = sinf(y * m_fDeg2Rad); const auto m_fCosY = cosf(y * m_fDeg2Rad); const auto m_fSinZ = sinf(z * m_fDeg2Rad); const auto m_fCosZ = cosf(z * m_fDeg2Rad); if (m_pForward) { m_pForward->x = m_fCosX * m_fCosY; m_pForward->y = -m_fSinX; m_pForward->z = m_fCosX * m_fSinY; } if (m_pRight) { m_pRight->x = -1.f * m_fSinZ * m_fSinX * m_fCosY + -1.f * m_fCosZ * -m_fSinY; m_pRight->y = -1.f * m_fSinZ * m_fCosX; m_pRight->z = -1.f * m_fSinZ * m_fSinX * m_fSinY + -1.f * m_fCosZ * m_fCosY; } if (m_pUp) { m_pUp->x = m_fCosZ * m_fSinX * m_fCosY + -m_fSinZ * -m_fSinY; m_pUp->y = m_fCosZ * m_fCosX; m_pUp->z = m_fCosZ * m_fSinX * m_fSinY + -m_fSinZ * m_fCosY; } } [[nodiscard]] auto Distance(const Vector3& event) const -> float { const auto dx = this->x - event.x; const auto dy = this->y - event.y; const auto dz = this->z - event.z; return std::sqrt(dx * dx + dy * dy + dz * dz); } auto operator*(const float x) -> Vector3 { this->x *= x; this->y *= x; this->z *= x; return *this; } auto operator-(const float x) -> Vector3 { this->x -= x; this->y -= x; this->z -= x; return *this; } auto operator+(const float x) -> Vector3 { this->x += x; this->y += x; this->z += x; return *this; } auto operator/(const float x) -> Vector3 { this->x /= x; this->y /= x; this->z /= x; return *this; } auto operator*(const Vector3 x) -> Vector3 { this->x *= x.x; this->y *= x.y; this->z *= x.z; return *this; } auto operator-(const Vector3 x) -> Vector3 { this->x -= x.x; this->y -= x.y; this->z -= x.z; return *this; } auto operator+(const Vector3 x) -> Vector3 { this->x += x.x; this->y += x.y; this->z += x.z; return *this; } auto operator/(const Vector3 x) -> Vector3 { this->x /= x.x; this->y /= x.y; this->z /= x.z; return *this; } auto operator ==(const Vector3 x) const -> bool { return this->x == x.x && this->y == x.y && this->z == x.z; } Vector3 cross(const Vector3& other) const { return Vector3( y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x ); } }; struct Vector2 { float x, y; Vector2() { x = y = 0.f; } Vector2(const float f1, const float f2) { x = f1; y = f2; } [[nodiscard]] auto Distance(const Vector2& event) const -> float { const auto dx = this->x - event.x; const auto dy = this->y - event.y; return std::sqrt(dx * dx + dy * dy); } auto operator*(const float x) -> Vector2 { this->x *= x; this->y *= x; return *this; } auto operator/(const float x) -> Vector2 { this->x /= x; this->y /= x; return *this; } auto operator+(const float x) -> Vector2 { this->x += x; this->y += x; return *this; } auto operator-(const float x) -> Vector2 { this->x -= x; this->y -= x; return *this; } auto operator*(const Vector2 x) -> Vector2 { this->x *= x.x; this->y *= x.y; return *this; } auto operator-(const Vector2 x) -> Vector2 { this->x -= x.x; this->y -= x.y; return *this; } auto operator+(const Vector2 x) -> Vector2 { this->x += x.x; this->y += x.y; return *this; } auto operator/(const Vector2 x) -> Vector2 { this->x /= x.x; this->y /= x.y; return *this; } auto operator ==(const Vector2 x) const -> bool { return this->x == x.x && this->y == x.y; } }; struct Vector2Int { int m_X, m_Y; Vector2Int() { m_X = m_Y = 0; } Vector2Int(const int f1, const int f2) { m_X = f1; m_Y = f2; } [[nodiscard]] auto Distance(const Vector2Int& event) const -> float { const auto dx = this->m_X - event.m_X; const auto dy = this->m_Y - event.m_Y; return std::sqrt(dx * dx + dy * dy); } auto operator*(const int x) -> Vector2Int { this->m_X *= x; this->m_Y *= x; return *this; } auto operator/(const int x) -> Vector2Int { this->m_X /= x; this->m_Y /= x; return *this; } auto operator+(const int x) -> Vector2Int { this->m_X += x; this->m_Y += x; return *this; } auto operator-(const int x) -> Vector2Int { this->m_X -= x; this->m_Y -= x; return *this; } auto operator*(const Vector2Int x) -> Vector2Int { this->m_X *= x.m_X; this->m_Y *= x.m_Y; return *this; } auto operator-(const Vector2Int x) -> Vector2Int { this->m_X -= x.m_X; this->m_Y -= x.m_Y; return *this; } auto operator+(const Vector2Int x) -> Vector2Int { this->m_X += x.m_X; this->m_Y += x.m_Y; return *this; } auto operator/(const Vector2Int x) -> Vector2Int { this->m_X /= x.m_X; this->m_Y /= x.m_Y; return *this; } auto operator ==(const Vector2Int x) const -> bool { return this->m_X == x.m_X && this->m_Y == x.m_Y; } }; struct Vector4 { float x, y, z, w; Vector4() { x = y = z = w = 0.F; } Vector4(const float f1, const float f2, const float f3, const float f4) { x = f1; y = f2; z = f3; w = f4; } auto operator*(const float x) -> Vector4 { this->x *= x; this->y *= x; this->z *= x; this->w *= x; return *this; } auto operator-(const float x) -> Vector4 { this->x -= x; this->y -= x; this->z -= x; this->w -= x; return *this; } auto operator+(const float x) -> Vector4 { this->x += x; this->y += x; this->z += x; this->w += x; return *this; } auto operator/(const float x) -> Vector4 { this->x /= x; this->y /= x; this->z /= x; this->w /= x; return *this; } auto operator*(const Vector4 x) -> Vector4 { this->x *= x.x; this->y *= x.y; this->z *= x.z; this->w *= x.w; return *this; } auto operator-(const Vector4 x) -> Vector4 { this->x -= x.x; this->y -= x.y; this->z -= x.z; this->w -= x.w; return *this; } auto operator+(const Vector4 x) -> Vector4 { this->x += x.x; this->y += x.y; this->z += x.z; this->w += x.w; return *this; } auto operator/(const Vector4 x) -> Vector4 { this->x /= x.x; this->y /= x.y; this->z /= x.z; this->w /= x.w; return *this; } auto operator ==(const Vector4 x) const -> bool { return this->x == x.x && this->y == x.y && this->z == x.z && this->w == x.w; } }; struct Quaternion { float x, y, z, w; Quaternion() { x = y = z = w = 0.F; } Quaternion(const float f1, const float f2, const float f3, const float f4) { x = f1; y = f2; z = f3; w = f4; } auto Euler(float m_fX, float m_fY, float m_fZ) -> Quaternion { constexpr auto m_fDeg2Rad = static_cast(3.1415926) / 180.F; m_fX = m_fX * m_fDeg2Rad * 0.5F; m_fY = m_fY * m_fDeg2Rad * 0.5F; m_fZ = m_fZ * m_fDeg2Rad * 0.5F; const auto m_fSinX = sinf(m_fX); const auto m_fCosX = cosf(m_fX); const auto m_fSinY = sinf(m_fY); const auto m_fCosY = cosf(m_fY); const auto m_fSinZ = sinf(m_fZ); const auto m_fCosZ = cosf(m_fZ); x = m_fCosY * m_fSinX * m_fCosZ + m_fSinY * m_fCosX * m_fSinZ; y = m_fSinY * m_fCosX * m_fCosZ - m_fCosY * m_fSinX * m_fSinZ; z = m_fCosY * m_fCosX * m_fSinZ - m_fSinY * m_fSinX * m_fCosZ; w = m_fCosY * m_fCosX * m_fCosZ + m_fSinY * m_fSinX * m_fSinZ; return *this; } auto Euler(const Vector3& m_vRot) -> Quaternion { return Euler(m_vRot.x, m_vRot.y, m_vRot.z); } [[nodiscard]] auto ToEuler() const -> Vector3 { Vector3 m_vEuler; const auto m_fDist = (x * x) + (y * y) + (z * z) + (w * w); if (const auto m_fTest = x * w - y * z; m_fTest > 0.4995F * m_fDist) { m_vEuler.x = static_cast(3.1415926) * 0.5F; m_vEuler.y = 2.F * atan2f(y, x); m_vEuler.z = 0.F; } else if (m_fTest < -0.4995F * m_fDist) { m_vEuler.x = static_cast(3.1415926) * -0.5F; m_vEuler.y = -2.F * atan2f(y, x); m_vEuler.z = 0.F; } else { m_vEuler.x = asinf(2.F * (w * x - y * z)); m_vEuler.y = atan2f(2.F * w * y + 2.F * z * x, 1.F - 2.F * (x * x + y * y)); m_vEuler.z = atan2f(2.F * w * z + 2.F * x * y, 1.F - 2.F * (z * z + x * x)); } constexpr auto m_fRad2Deg = 180.F / static_cast(3.1415926); m_vEuler.x *= m_fRad2Deg; m_vEuler.y *= m_fRad2Deg; m_vEuler.z *= m_fRad2Deg; return m_vEuler; } auto operator*(const float x) -> Quaternion { this->x *= x; this->y *= x; this->z *= x; this->w *= x; return *this; } auto operator-(const float x) -> Quaternion { this->x -= x; this->y -= x; this->z -= x; this->w -= x; return *this; } auto operator+(const float x) -> Quaternion { this->x += x; this->y += x; this->z += x; this->w += x; return *this; } auto operator/(const float x) -> Quaternion { this->x /= x; this->y /= x; this->z /= x; this->w /= x; return *this; } auto operator*(const Quaternion x) -> Quaternion { this->x *= x.x; this->y *= x.y; this->z *= x.z; this->w *= x.w; return *this; } auto operator-(const Quaternion x) -> Quaternion { this->x -= x.x; this->y -= x.y; this->z -= x.z; this->w -= x.w; return *this; } auto operator+(const Quaternion x) -> Quaternion { this->x += x.x; this->y += x.y; this->z += x.z; this->w += x.w; return *this; } auto operator/(const Quaternion x) -> Quaternion { this->x /= x.x; this->y /= x.y; this->z /= x.z; this->w /= x.w; return *this; } auto operator ==(const Quaternion x) const -> bool { return this->x == x.x && this->y == x.y && this->z == x.z && this->w == x.w; } }; struct Bounds { Vector3 m_vCenter; Vector3 m_vExtents; }; struct Plane { Vector3 m_vNormal; float fDistance; }; struct Ray { Vector3 m_vOrigin; Vector3 m_vDirection; }; struct Rect { float fX, fY; float fWidth, fHeight; Rect() { fX = fY = fWidth = fHeight = 0.f; } Rect(const float f1, const float f2, const float f3, const float f4) { fX = f1; fY = f2; fWidth = f3; fHeight = f4; } }; struct Color { float r, g, b, a; Color() { r = g = b = a = 0.f; } explicit Color(const float fRed = 0.f, const float fGreen = 0.f, const float fBlue = 0.f, const float fAlpha = 1.f) { r = fRed; g = fGreen; b = fBlue; a = fAlpha; } }; struct Matrix4x4 { float m[4][4] = { {0} }; Matrix4x4() = default; auto operator[](const int i) -> float* { return m[i]; } }; struct Object { union { void* klass{ nullptr }; void* vtable; } Il2CppClass; struct MonitorData* monitor{ nullptr }; auto GetType() -> CsType* { if (!this) return nullptr; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("Object", "System")->Get("GetType"); if (method) return method->Invoke(this); return nullptr; } auto ToString() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("Object", "System")->Get("ToString"); if (method) return method->Invoke(this)->ToString(); return {}; } }; struct CsType { auto FormatTypeName() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("Type", "System", "MemberInfo")->Get("FormatTypeName"); if (method) return method->Invoke(this)->ToString(); return {}; } auto GetFullName() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("Type", "System", "MemberInfo")->Get("get_FullName"); if (method) return method->Invoke(this)->ToString(); return {}; } auto GetNamespace() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("Type", "System", "MemberInfo")->Get("get_Namespace"); if (method) return method->Invoke(this)->ToString(); return {}; } }; struct String { // int32_t m_stringLength{ 0 }; // wchar_t m_firstChar[32]{}; Object object; int32_t length; ///< Length of string *excluding* the trailing null (which is included in ///< 'chars'). char16_t chars[1]; [[nodiscard]] auto ToString() const -> std::string { #if WINDOWS_MODE if (IsBadReadPtr(this, sizeof(String))) return {}; if (IsBadReadPtr(m_firstChar, m_stringLength)) return {}; #endif if (!this) return {}; try { // using convert_typeX = std::codecvt_utf8; // std::wstring_convert converterX; // return converterX.to_bytes(m_firstChar); return GakumasLocal::Misc::ToUTF8(chars); } catch (std::exception& e) { std::cout << "String Invoke Error\n"; GakumasLocal::Log::ErrorFmt("String Invoke Error: %s", e.what()); return {}; } } [[nodiscard]] auto ToWString() const -> std::u16string { #if WINDOWS_MODE if (IsBadReadPtr(this, sizeof(String))) return {}; if (IsBadReadPtr(m_firstChar, m_stringLength)) return {}; #endif if (!this) return {}; try { // using convert_typeX = std::codecvt_utf8; // std::wstring_convert converterX; // return converterX.to_bytes(m_firstChar); return {chars}; } catch (std::exception& e) { std::cout << "String Invoke Error\n"; GakumasLocal::Log::ErrorFmt("String Invoke Error: %s", e.what()); return {}; } } auto operator=(const std::string& newString) const -> String* { return New(newString); } auto operator==(const std::wstring& newString) const -> bool { return Equals(newString); } auto Clear() -> void { if (!this) return; memset(chars, 0, length); length = 0; } [[nodiscard]] auto Equals(const std::wstring& newString) const -> bool { if (!this) return false; if (newString.size() != length) return false; if (std::memcmp(newString.data(), chars, length) != 0) return false; return true; } static auto New(const std::string& str) -> String* { if (mode_ == Mode::Il2Cpp) return UnityResolve::Invoke("il2cpp_string_new", str.c_str()); return UnityResolve::Invoke("mono_string_new", UnityResolve::Invoke("mono_get_root_domain"), str.c_str()); } }; template struct Array : Object { struct { std::uintptr_t length; std::int32_t lower_bound; }*bounds{ nullptr }; std::uintptr_t max_length{ 0 }; __declspec(align(8)) T** vector {}; auto GetData() -> uintptr_t { return reinterpret_cast(&vector); } auto operator[](const unsigned int m_uIndex) -> T& { return *reinterpret_cast(GetData() + sizeof(T) * m_uIndex); } auto At(const unsigned int m_uIndex) -> T& { return operator[](m_uIndex); } auto Insert(T* m_pArray, uintptr_t m_uSize, const uintptr_t m_uIndex = 0) -> void { if ((m_uSize + m_uIndex) >= max_length) { if (m_uIndex >= max_length) return; m_uSize = max_length - m_uIndex; } for (uintptr_t u = 0; m_uSize > u; ++u) operator[](u + m_uIndex) = m_pArray[u]; } auto Fill(T m_tValue) -> void { for (uintptr_t u = 0; max_length > u; ++u) operator[](u) = m_tValue; } auto RemoveAt(const unsigned int m_uIndex) -> void { if (m_uIndex >= max_length) return; if (max_length > (m_uIndex + 1)) for (auto u = m_uIndex; (max_length - m_uIndex) > u; ++u) operator[](u) = operator[](u + 1); --max_length; } auto RemoveRange(const unsigned int m_uIndex, unsigned int m_uCount) -> void { if (m_uCount == 0) m_uCount = 1; const auto m_uTotal = m_uIndex + m_uCount; if (m_uTotal >= max_length) return; if (max_length > (m_uTotal + 1)) for (auto u = m_uIndex; (max_length - m_uTotal) >= u; ++u) operator[](u) = operator[](u + m_uCount); max_length -= m_uCount; } auto RemoveAll() -> void { if (max_length > 0) { memset(GetData(), 0, sizeof(Type) * max_length); max_length = 0; } } auto ToVector() -> std::vector { #if WINDOWS_MODE if (IsBadReadPtr(this, sizeof(Array))) return {}; #endif if (!this) return {}; try { std::vector rs{}; rs.reserve(this->max_length); for (auto i = 0; i < this->max_length; i++) rs.push_back(this->At(i)); return rs; } catch (...) { std::cout << "Array Invoke Error\n"; return {}; } } auto Resize(int newSize) -> void { static Method* method; if (!method) method = Get("mscorlib.dll")->Get("Array")->Get("Resize"); if (method) return method->Invoke(this, newSize); } static auto New(const Class* kalss, const std::uintptr_t size) -> Array* { if (mode_ == Mode::Il2Cpp) return UnityResolve::Invoke("il2cpp_array_new", kalss->address, size); return UnityResolve::Invoke("mono_array_new", pDomain, kalss->address, size); } }; template struct List : Object { Array* pList; int size{}; int version{}; void* syncRoot{}; auto ToArray() -> Array* { return pList; } static auto New(const Class* kalss, const std::uintptr_t size) -> List* { auto pList = new List(); pList->pList = Array::New(kalss, size); pList->size = size; } auto operator[](const unsigned int m_uIndex) -> Type& { return pList->At(m_uIndex); } auto Add(Type pDate) -> void { if (!this) return; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("Add"); if (method) return method->Invoke(this, pDate); } auto Remove(Type pDate) -> bool { if (!this) return false; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("Remove"); if (method) return method->Invoke(this, pDate); return false; } auto RemoveAt(int index) -> void { if (!this) return; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("RemoveAt"); if (method) return method->Invoke(this, index); } auto ForEach(void(*action)(Type pDate)) -> void { if (!this) return; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("ForEach"); if (method) return method->Invoke(this, action); } auto GetRange(int index, int count) -> List* { if (!this) return {}; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("GetRange"); if (method) return method->Invoke(this, index, count); return nullptr; } auto Clear() -> void { if (!this) return; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("Clear"); if (method) return method->Invoke(this); } auto Sort(int (*comparison)(Type* pX, Type* pY)) -> void { if (!this) return; static Method* method; if (!method) method = Get("mscorlib.dll")->Get("List`1")->Get("Sort", { "*" }); if (method) return method->Invoke(this, comparison); } }; template struct Dictionary : Object { struct Entry { int iHashCode; int iNext; TKey tKey; TValue tValue; }; Array* pBuckets; Array* pEntries; int iCount; int iVersion; int iFreeList; int iFreeCount; void* pComparer; void* pKeys; void* pValues; auto GetEntry() -> Entry* { return static_cast(pEntries->GetData()); } auto GetKeyByIndex(const int iIndex) -> TKey { TKey tKey = { 0 }; Entry* pEntry = GetEntry(); if (pEntry) tKey = pEntry[iIndex].m_tKey; return tKey; } auto GetValueByIndex(const int iIndex) -> TValue { TValue tValue = { 0 }; Entry* pEntry = GetEntry(); if (pEntry) tValue = pEntry[iIndex].m_tValue; return tValue; } auto GetValueByKey(const TKey tKey) -> TValue { TValue tValue = { 0 }; for (auto i = 0; i < iCount; i++) if (GetEntry()[i].m_tKey == tKey) tValue = GetEntry()[i].m_tValue; return tValue; } auto operator[](const TKey tKey) const -> TValue { return GetValueByKey(tKey); } }; struct UnityObject : Object { void* m_CachedPtr; auto GetName() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("get_name"); if (method) return method->Invoke(this)->ToString(); return {}; } auto ToString() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("ToString"); if (method) return method->Invoke(this)->ToString(); return {}; } static auto ToString(UnityObject* obj) -> std::string { if (!obj) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("ToString", { "*" }); if (method) return method->Invoke(obj)->ToString(); return {}; } static auto Instantiate(UnityObject* original) -> UnityObject* { if (!original) return nullptr; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("Instantiate", { "*" }); if (method) return method->Invoke(original); return nullptr; } static auto Destroy(UnityObject* original) -> void { if (!original) return; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("Destroy", { "*" }); if (method) return method->Invoke(original); } static auto op_Implicit(UnityObject* exists) -> bool { if (!exists) return false; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object", "UnityEngine")->Get("op_Implicit"); if (method) return method->Invoke(exists); return false; } }; struct Component : UnityObject { auto GetTransform() -> Transform* { if (!this) return nullptr; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("get_transform"); if (method) return method->Invoke(this); return nullptr; } auto GetGameObject() -> GameObject* { if (!this) return nullptr; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("get_gameObject"); if (method) return method->Invoke(this); return nullptr; } auto GetTag() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("get_tag"); if (method) return method->Invoke(this)->ToString(); return {}; } template auto GetComponentsInChildren() -> std::vector { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentsInChildren"); if (method) return method->Invoke*>(this)->ToVector(); return {}; } template auto GetComponentsInChildren(Class* pClass) -> std::vector { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentsInChildren", { "System.Type" }); if (method) return method->Invoke*>(this, pClass->GetType())->ToVector(); return {}; } template auto GetComponents() -> std::vector { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponents"); if (method) return method->Invoke*>(this)->ToVector(); return {}; } template auto GetComponents(Class* pClass) -> std::vector { static Method* method; static void* obj; if (!this) return std::vector(); if (!method || !obj) { method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponents", { "System.Type" }); obj = pClass->GetType(); } if (method) return method->Invoke*>(this, obj)->ToVector(); return {}; } template auto GetComponentsInParent() -> std::vector { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentsInParent"); if (method) return method->Invoke*>(this)->ToVector(); return {}; } template auto GetComponentsInParent(Class* pClass) -> std::vector { static Method* method; static void* obj; if (!this) return std::vector(); if (!method || !obj) { method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentsInParent", { "System.Type" }); obj = pClass->GetType(); } if (method) return method->Invoke*>(this, obj)->ToVector(); return {}; } template auto GetComponentInChildren(Class* pClass) -> T { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentInChildren", { "System.Type" }); if (method) return method->Invoke(this, pClass->GetType()); return T(); } template auto GetComponentInParent(Class* pClass) -> T { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentInParent", { "System.Type" }); if (method) return method->Invoke(this, pClass->GetType()); return T(); } }; struct Camera : Component { enum class Eye : int { Left, Right, Mono }; static auto GetMain() -> Camera* { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_main"); if (method) return method->Invoke(); return nullptr; } static auto GetCurrent() -> Camera* { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_current"); if (method) return method->Invoke(); return nullptr; } static auto GetAllCount() -> int { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_allCamerasCount"); if (method) return method->Invoke(); return 0; } static auto GetAllCamera() -> std::vector { static Method* method; static Class* klass; if (!method || !klass) { method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("GetAllCameras", { "*" }); klass = Get("UnityEngine.CoreModule.dll")->Get("Camera"); } if (method && klass) { if (const int count = GetAllCount(); count != 0) { const auto array = Array::New(klass, count); method->Invoke(array); return array->ToVector(); } } return {}; } auto GetDepth() -> float { if (!this) return 0.0f; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_depth"); if (method) return method->Invoke(this); return 0.0f; } auto SetDepth(const float depth) -> void { if (!this) return; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("set_depth", { "*" }); if (method) return method->Invoke(this, depth); } auto SetFoV(const float fov) -> void { if (!this) return; static Method* method_fieldOfView; if (!method_fieldOfView) method_fieldOfView = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("set_fieldOfView", { "*" }); if (method_fieldOfView) return method_fieldOfView->Invoke(this, fov); } auto GetFoV() -> float { if (!this) return 0.0f; static Method* method_fieldOfView; if (!method_fieldOfView) method_fieldOfView = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_fieldOfView"); if (method_fieldOfView) return method_fieldOfView->Invoke(this); return 0.0f; } auto WorldToScreenPoint(const Vector3& position, const Eye eye = Eye::Mono) -> Vector3 { if (!this) return { -100, -100, -100 }; static Method* method; if (!method) { if (mode_ == Mode::Mono) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("WorldToScreenPoint_Injected"); else method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("WorldToScreenPoint", { "*", "*" }); } if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, position, eye, &vec3); return vec3; } if (method) return method->Invoke(this, position, eye); return {}; } auto ScreenToWorldPoint(const Vector3& position, const Eye eye = Eye::Mono) -> Vector3 { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get(mode_ == Mode::Mono ? "ScreenToWorldPoint_Injected" : "ScreenToWorldPoint"); if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, position, eye, &vec3); return vec3; } if (method) return method->Invoke(this, position, eye); return {}; } auto CameraToWorldMatrix() -> Matrix4x4 { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get(mode_ == Mode::Mono ? "get_cameraToWorldMatrix_Injected" : "get_cameraToWorldMatrix"); if (mode_ == Mode::Mono && method) { Matrix4x4 matrix4{}; method->Invoke(this, &matrix4); return matrix4; } if (method) return method->Invoke(this); return {}; } auto GetPixelRect() -> Rect { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_pixelRect"); return method->Invoke(this); } auto GetOrthographicSize() -> float { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_orthographicSize"); return method->Invoke(this); } void SetNearClipPlane(float value) { if (!this) return; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("set_nearClipPlane"); return method->Invoke(this, value); } float GetNearClipPlane() { if (!this) return -1; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("get_nearClipPlane"); return method->Invoke(this); } }; struct Transform : Component { auto GetPosition() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "get_position_Injected" : "get_position"); if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, &vec3); return vec3; } if (method) return method->Invoke(this); return {}; } auto SetPosition(const Vector3& position) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "set_position_Injected" : "set_position"); if (mode_ == Mode::Mono && method) return method->Invoke(this, &position); if (method) return method->Invoke(this, position); } auto GetRight() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("get_right"); if (method) return method->Invoke(this); return {}; } auto SetRight(const Vector3& value) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("set_right"); if (method) return method->Invoke(this, value); } auto GetUp() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("get_up"); if (method) return method->Invoke(this); return {}; } auto SetUp(const Vector3& value) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("set_up"); if (method) return method->Invoke(this, value); } auto GetForward() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("get_forward"); if (method) return method->Invoke(this); return {}; } auto SetForward(const Vector3& value) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("set_forward"); if (method) return method->Invoke(this, value); } auto GetRotation() -> Quaternion { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "get_rotation_Injected" : "get_rotation"); if (mode_ == Mode::Mono && method) { const Quaternion vec3{}; method->Invoke(this, &vec3); return vec3; } if (method) return method->Invoke(this); return {}; } auto SetRotation(const Quaternion& position) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "set_rotation_Injected" : "set_rotation"); if (mode_ == Mode::Mono && method) return method->Invoke(this, &position); if (method) return method->Invoke(this, position); } auto GetLocalPosition() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "get_localPosition_Injected" : "get_localPosition"); if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, &vec3); return vec3; } if (method) return method->Invoke(this); return {}; } auto SetLocalPosition(const Vector3& position) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "set_localPosition_Injected" : "set_localPosition"); if (mode_ == Mode::Mono && method) return method->Invoke(this, &position); if (method) return method->Invoke(this, position); } auto GetLocalRotation() -> Quaternion { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "get_localRotation_Injected" : "get_localRotation"); if (mode_ == Mode::Mono && method) { const Quaternion vec3{}; method->Invoke(this, &vec3); return vec3; } if (method) return method->Invoke(this); return {}; } auto SetLocalRotation(const Quaternion& position) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "set_localRotation_Injected" : "set_localRotation"); if (mode_ == Mode::Mono && method) return method->Invoke(this, &position); if (method) return method->Invoke(this, position); } auto GetLocalScale() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "get_localScale_Injected" : "get_localScale"); if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, &vec3); return vec3; } if (method) return method->Invoke(this); return {}; } auto SetLocalScale(const Vector3& position) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "set_localScale_Injected" : "set_localScale"); if (mode_ == Mode::Mono && method) return method->Invoke(this, &position); if (method) return method->Invoke(this, position); } auto GetChildCount() -> int { static Method* method; if (!this) return 0; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("get_childCount"); if (method) return method->Invoke(this); return 0; } auto GetChild(const int index) -> Transform* { static Method* method; if (!this) return nullptr; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("GetChild"); if (method) return method->Invoke(this, index); return nullptr; } auto GetRoot() -> Transform* { static Method* method; if (!this) return nullptr; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("GetRoot"); if (method) return method->Invoke(this); return nullptr; } auto GetParent() -> Transform* { static Method* method; if (!this) return nullptr; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("GetParent"); if (method) return method->Invoke(this); return nullptr; } auto GetLossyScale() -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "get_lossyScale_Injected" : "get_lossyScale"); if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, &vec3); return vec3; } if (method) return method->Invoke(this); return {}; } auto TransformPoint(const Vector3& position) -> Vector3 { static Method* method; if (!this) return {}; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get(mode_ == Mode::Mono ? "TransformPoint_Injected" : "TransformPoint"); if (mode_ == Mode::Mono && method) { const Vector3 vec3{}; method->Invoke(this, position, &vec3); return vec3; } if (method) return method->Invoke(this, position); return {}; } auto LookAt(const Vector3& worldPosition) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("LookAt", { "Vector3" }); if (method) return method->Invoke(this, worldPosition); } auto Rotate(const Vector3& eulers) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Transform")->Get("Rotate", { "Vector3" }); if (method) return method->Invoke(this, eulers); } }; struct GameObject : UnityObject { static auto Create(GameObject* obj, const std::string& name) -> void { if (!obj) return; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("Internal_CreateGameObject"); if (method) method->Invoke(obj, String::New(name)); } static auto FindGameObjectsWithTag(const std::string& name) -> std::vector { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("FindGameObjectsWithTag"); if (method) { const auto array = method->Invoke*>(String::New(name)); return array->ToVector(); } return {}; } static auto Find(const std::string& name) -> GameObject* { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("Find"); if (method) return method->Invoke(String::New(name)); return nullptr; } auto GetActive() -> bool { static Method* method; if (!this) return false; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_active"); if (method) return method->Invoke(this); return false; } auto SetActive(bool value) -> void { static Method* method; if (!this) return; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("set_active"); if (method) return method->Invoke(this, value); } auto GetActiveSelf() -> bool { static Method* method; if (!this) return false; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_activeSelf"); if (method) return method->Invoke(this); return false; } auto GetActiveInHierarchy() -> bool { static Method* method; if (!this) return false; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_activeInHierarchy"); if (method) return method->Invoke(this); return false; } auto GetIsStatic() -> bool { static Method* method; if (!this) return false; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_isStatic"); if (method) return method->Invoke(this); return false; } auto GetTransform() -> Transform* { static Method* method; if (!this) return nullptr; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_transform"); if (method) return method->Invoke(this); return nullptr; } auto GetTag() -> std::string { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_tag"); if (method) return method->Invoke(this)->ToString(); return {}; } template auto GetComponent() -> T { if (!this) return T(); static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponent"); if (method) return method->Invoke(this); return T(); } template auto GetComponent(Class* type) -> T { if (!this) return T(); static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponent", { "System.Type" }); if (method) return method->Invoke(this, type->GetType()); return T(); } template auto GetComponentInChildren(Class* type) -> T { if (!this) return T(); static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponentInChildren", { "System.Type" }); if (method) return method->Invoke(this, type->GetType()); return T(); } template auto GetComponentInParent(Class* type) -> T { if (!this) return T(); static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponentInParent", { "System.Type" }); if (method) return method->Invoke(this, type->GetType()); return T(); } template auto GetComponents(Class* type, bool useSearchTypeAsArrayReturnType = false, bool recursive = false, bool includeInactive = true, bool reverse = false, List* resultList = nullptr) -> std::vector { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponentsInternal"); if (method) return method->Invoke*>(this, type->GetType(), useSearchTypeAsArrayReturnType, recursive, includeInactive, reverse, resultList)->ToVector(); return {}; } template auto GetComponentsInChildren(Class* type, const bool includeInactive = false) -> std::vector { return GetComponents(type, false, true, includeInactive, false, nullptr); } template auto GetComponentsInParent(Class* type, const bool includeInactive = false) -> std::vector { return GetComponents(type, false, true, includeInactive, true, nullptr); } }; struct LayerMask : Object { int m_Mask; static auto NameToLayer(const std::string& layerName) -> int { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("LayerMask")->Get("NameToLayer"); if (method) return method->Invoke(String::New(layerName)); return 0; } static auto LayerToName(const int layer) -> std::string { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("LayerMask")->Get("LayerToName"); if (method) return method->Invoke(layer)->ToString(); return {}; } }; struct Rigidbody : Component { auto GetDetectCollisions() -> bool { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Rigidbody")->Get("get_detectCollisions"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } auto SetDetectCollisions(const bool value) -> void { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Rigidbody")->Get("set_detectCollisions"); if (method) return method->Invoke(this, value); throw std::logic_error("nullptr"); } auto GetVelocity() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Rigidbody")->Get(mode_ == Mode::Mono ? "get_velocity_Injected" : "get_velocity"); if (mode_ == Mode::Mono && method) { Vector3 vector; method->Invoke(this, &vector); return vector; } if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } auto SetVelocity(Vector3 value) -> void { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Rigidbody")->Get(mode_ == Mode::Mono ? "set_velocity_Injected" : "set_velocity"); if (mode_ == Mode::Mono && method) return method->Invoke(this, &value); if (method) return method->Invoke(this, value); throw std::logic_error("nullptr"); } }; struct Collider : Component { auto GetBounds() -> Bounds { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Collider")->Get("get_bounds_Injected"); if (method) { Bounds bounds; method->Invoke(this, &bounds); return bounds; } return {}; } }; struct Mesh : UnityObject { auto GetBounds() -> Bounds { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Mesh")->Get("get_bounds_Injected"); if (method) { Bounds bounds; method->Invoke(this, &bounds); return bounds; } return {}; } }; struct CapsuleCollider : Collider { auto GetCenter() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("CapsuleCollider")->Get("get_center"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } auto GetDirection() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("CapsuleCollider")->Get("get_direction"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } auto GetHeightn() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("CapsuleCollider")->Get("get_height"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } auto GetRadius() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("CapsuleCollider")->Get("get_radius"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } }; struct BoxCollider : Collider { auto GetCenter() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("BoxCollider")->Get("get_center"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } auto GetSize() -> Vector3 { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("BoxCollider")->Get("get_size"); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } }; struct Renderer : Component { auto GetBounds() -> Bounds { if (!this) return {}; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Renderer")->Get("get_bounds_Injected"); if (method) { Bounds bounds; method->Invoke(this, &bounds); return bounds; } return {}; } }; struct Behaviour : Component { auto GetEnabled() -> bool { if (!this) return false; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Behaviour")->Get("get_enabled"); if (method) return method->Invoke(this); return false; } auto SetEnabled(const bool value) -> void { if (!this) return; static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Behaviour")->Get("set_enabled"); if (method) return method->Invoke(this, value); } }; struct MonoBehaviour : Behaviour {}; struct Physics : Object { static auto Linecast(const Vector3& start, const Vector3& end) -> bool { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("Linecast", { "*", "*" }); if (method) return method->Invoke(start, end); return false; } static auto Raycast(const Vector3& origin, const Vector3& direction, const float maxDistance) -> bool { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("Raycast", { "*", "*", "*" }); if (method) return method->Invoke(origin, direction, maxDistance); return false; } static auto IgnoreCollision(Collider* collider1, Collider* collider2) -> void { static Method* method; if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("IgnoreCollision1", { "*", "*" }); if (method) return method->Invoke(collider1, collider2); } }; struct Time { static auto GetTime() -> float { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Time")->Get("get_time"); if (method) return method->Invoke(); return 0.0f; } static auto GetDeltaTime() -> float { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Time")->Get("get_deltaTime"); if (method) return method->Invoke(); return 0.0f; } static auto GetFixedDeltaTime() -> float { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Time")->Get("get_fixedDeltaTime"); if (method) return method->Invoke(); return 0.0f; } static auto GetTimeScale() -> float { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Time")->Get("get_timeScale"); if (method) return method->Invoke(); return 0.0f; } static auto SetTimeScale(float value) -> void { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Time")->Get("set_timeScale"); if (method) return method->Invoke(value); } }; struct Animator : Behaviour { enum class HumanBodyBones : int { Hips, LeftUpperLeg, RightUpperLeg, LeftLowerLeg, RightLowerLeg, LeftFoot, RightFoot, Spine, Chest, UpperChest = 54, Neck = 9, Head, LeftShoulder, RightShoulder, LeftUpperArm, RightUpperArm, LeftLowerArm, RightLowerArm, LeftHand, RightHand, LeftToes, RightToes, LeftEye, RightEye, Jaw, LeftThumbProximal, LeftThumbIntermediate, LeftThumbDistal, LeftIndexProximal, LeftIndexIntermediate, LeftIndexDistal, LeftMiddleProximal, LeftMiddleIntermediate, LeftMiddleDistal, LeftRingProximal, LeftRingIntermediate, LeftRingDistal, LeftLittleProximal, LeftLittleIntermediate, LeftLittleDistal, RightThumbProximal, RightThumbIntermediate, RightThumbDistal, RightIndexProximal, RightIndexIntermediate, RightIndexDistal, RightMiddleProximal, RightMiddleIntermediate, RightMiddleDistal, RightRingProximal, RightRingIntermediate, RightRingDistal, RightLittleProximal, RightLittleIntermediate, RightLittleDistal, LastBone = 55 }; auto GetBoneTransform(const HumanBodyBones humanBoneId) -> Transform* { #if WINDOWS_MODE if (IsBadReadPtr(this, sizeof(Animator))) return nullptr; #endif static Method* method; if (!this) return nullptr; if (!method) method = Get("UnityEngine.AnimationModule.dll")->Get("Animator")->Get("GetBoneTransform"); if (method) return method->Invoke(this, humanBoneId); return nullptr; } }; template static auto Invoke(const void* address, Args... args) -> Return { #if WINDOWS_MODE try { bool badPtr; if (!badPtr) badPtr = !IsBadCodePtr(FARPROC(address)); if (address != nullptr && badPtr) return reinterpret_cast(address)(args...); } catch (...) {} #elif LINUX_MODE || ANDROID_MODE try { if (address != nullptr) return reinterpret_cast(address)(args...); } catch (...) {} #endif return Return(); } }; private: inline static Mode mode_{}; inline static void* hmodule_; inline static bool lazyInit_; inline static std::unordered_map address_{}; inline static void* pDomain{}; }; #endif // UNITYRESOLVE_HPP