#include "RemoteCallAPI.h" #include #include #include extern Logger logger; namespace RemoteCall { CallbackFn const EMPTY_FUNC{}; std::unordered_map exportedFuncs; bool exportFunc(std::string const& nameSpace, std::string const& funcName, CallbackFn&& callback, HMODULE handle) { if (nameSpace.find("::") != nameSpace.npos) { logger.error("Namespace can't includes \"::\""); return false; } if (exportedFuncs.count(nameSpace + "::" + funcName) != 0) return false; exportedFuncs.emplace(nameSpace + "::" + funcName, ExportedFuncData{handle, std::move(callback)}); return true; } CallbackFn const& importFunc(std::string const& nameSpace, std::string const& funcName) { auto iter = exportedFuncs.find(nameSpace + "::" + funcName); if (iter == exportedFuncs.end()) return EMPTY_FUNC; return iter->second.callback; } bool hasFunc(std::string const& nameSpace, std::string const& funcName) { return exportedFuncs.find(nameSpace + "::" + funcName) != exportedFuncs.end(); } bool removeFunc(std::string&& key) { return exportedFuncs.erase(key); } bool removeFunc(std::string const& nameSpace, std::string const& funcName) { return removeFunc(nameSpace + "::" + funcName); } void _onCallError(std::string const& msg, HMODULE handle) { logger.error(msg); auto plugin = LL::getPlugin(handle); if (plugin) logger.error("In plugin <{}>", plugin->name); } int removeNameSpace(std::string const& nameSpace) { int count = 0; for (auto iter = exportedFuncs.begin(); iter != exportedFuncs.end();) { if (SplitStrWithPattern(iter->first, "::")[0] == nameSpace) { iter = exportedFuncs.erase(iter); ++count; } else ++iter; } return count; } int removeFuncs(std::vector> funcs) { int count = 0; for (auto& [ns, name] : funcs) { if (removeFunc(ns + "::" + name)) count++; } return count; } } // namespace RemoteCall static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); // static_assert(RemoteCall::is_supported_type_v); static_assert(RemoteCall::is_supported_type_v); #ifdef DEBUG #include #include inline bool testExtra = ([]() { std::vector input{"aa", "abcd", "test"}; auto output = RemoteCall::extract(RemoteCall::pack(input)); assert(output == input); std::unordered_map input2{ {"aa", "bb"}, {"ab", "ba"}, {"abc", "cba"}, }; auto output2 = RemoteCall::extract(RemoteCall::pack(input2)); assert(output2 == input2); std::vector input3{input2, input2}; auto output3 = RemoteCall::extract(RemoteCall::pack(input3)); assert(output3 == input3); std::unordered_map input4{ {"aa", input3}, {"ab", input3}, {"abc", input3}, }; auto output4 = RemoteCall::extract(RemoteCall::pack(input4)); assert(output4 == input4); std::vector input5{input4, input4, input4}; auto output5 = RemoteCall::extract(RemoteCall::pack(input5)); assert(output5 == input5); #if false __debugbreak(); output5.erase(output5.begin()); assert(output5 == input5); __debugbreak(); #endif // false return true; })(); int TestExport(std::string a0, int a1, int a2) { return static_cast(a0.size()) + a1; } std::unique_ptr TestSimulatedPlayerLL(Player* player) { return player->getNbt(); } void exportTestSimulatedPlayerLL() { RemoteCall::exportAs("TestRemoteCall", "TestSimulatedPlayerLL", TestSimulatedPlayerLL); } #include auto TestRemoteCall = ([]() -> bool { std::thread([]() { Sleep(5000); Schedule::nextTick([]() { RemoteCall::exportAs("TestNameSpace", "StrSize", [](std::string arg) -> size_t { return arg.size(); }); exportTestSimulatedPlayerLL(); RemoteCall::exportAs("Test", "test2", TestExport); if (!RemoteCall::hasFunc("TestRemoteCall", "TestSimulatedPlayerJs")) return; auto func = RemoteCall::importAs("Test", "test2"); auto func2 = RemoteCall::importAs>("Test", "test2"); auto size = func("TestParam", 5, 10); static auto TestSimulatedPlayerJs = RemoteCall::importAs("TestRemoteCall", "TestSimulatedPlayerJs"); Event::PlayerJoinEvent::subscribe_ref([](Event::PlayerJoinEvent& ev) { logger.warn("TestSimulatedPlayer"); auto res = TestSimulatedPlayerJs(ev.mPlayer); logger.warn("Result: {}", res); return true; }); }); }).detach(); return true; })(); #endif // DEBUG