LiteLoaderBDS-1.16.40/LiteLoader/Kernel/RemoteCallAPI.cpp
2022-09-21 19:47:03 +08:00

164 lines
5.7 KiB
C++

#include "RemoteCallAPI.h"
#include <LoggerAPI.h>
#include <Utils/StringHelper.h>
#include <LLAPI.h>
extern Logger logger;
namespace RemoteCall {
CallbackFn const EMPTY_FUNC{};
std::unordered_map<std::string, RemoteCall::ExportedFuncData> 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<std::pair<std::string, std::string>> 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<void>);
static_assert(RemoteCall::is_supported_type_v<int>);
static_assert(RemoteCall::is_supported_type_v<bool>);
static_assert(RemoteCall::is_supported_type_v<float>);
static_assert(RemoteCall::is_supported_type_v<size_t>);
static_assert(RemoteCall::is_supported_type_v<Player*>);
static_assert(RemoteCall::is_supported_type_v<Actor*>);
static_assert(RemoteCall::is_supported_type_v<Mob*>);
static_assert(RemoteCall::is_supported_type_v<BlockActor*>);
static_assert(RemoteCall::is_supported_type_v<Block*>);
static_assert(RemoteCall::is_supported_type_v<Vec3>);
static_assert(RemoteCall::is_supported_type_v<Vec3&>);
static_assert(RemoteCall::is_supported_type_v<Vec3 const&>);
// static_assert(RemoteCall::is_supported_type_v<Vec3 const*>);
static_assert(RemoteCall::is_supported_type_v<CompoundTag*>);
#ifdef DEBUG
#include <ScheduleAPI.h>
#include <MC/Player.hpp>
inline bool testExtra = ([]() {
std::vector<std::string> input{"aa", "abcd", "test"};
auto output = RemoteCall::extract<decltype(input)>(RemoteCall::pack(input));
assert(output == input);
std::unordered_map<std::string, std::string> input2{
{"aa", "bb"},
{"ab", "ba"},
{"abc", "cba"},
};
auto output2 = RemoteCall::extract<decltype(input2)>(RemoteCall::pack(input2));
assert(output2 == input2);
std::vector<decltype(input2)> input3{input2, input2};
auto output3 = RemoteCall::extract<decltype(input3)>(RemoteCall::pack(input3));
assert(output3 == input3);
std::unordered_map<std::string, decltype(input3)> input4{
{"aa", input3},
{"ab", input3},
{"abc", input3},
};
auto output4 = RemoteCall::extract<decltype(input4)>(RemoteCall::pack(input4));
assert(output4 == input4);
std::vector<decltype(input4)> input5{input4, input4, input4};
auto output5 = RemoteCall::extract<decltype(input5)>(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<int>(a0.size()) + a1;
}
std::unique_ptr<CompoundTag> TestSimulatedPlayerLL(Player* player) {
return player->getNbt();
}
void exportTestSimulatedPlayerLL() {
RemoteCall::exportAs("TestRemoteCall", "TestSimulatedPlayerLL", TestSimulatedPlayerLL);
}
#include <EventAPI.h>
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<decltype(TestExport)>("Test", "test2");
auto func2 = RemoteCall::importAs<std::function<decltype(TestExport)>>("Test", "test2");
auto size = func("TestParam", 5, 10);
static auto TestSimulatedPlayerJs = RemoteCall::importAs<bool(Player*)>("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