LiteLoaderBDS-1.16.40/ScriptEngine/API/LlAPI.cpp
2022-09-21 19:47:03 +08:00

377 lines
13 KiB
C++

#include "APIHelp.h"
#include <LiteLoader/Main/Config.h>
#include "LlAPI.h"
#include <Engine/GlobalShareData.h>
#include <Engine/EngineOwnData.h>
#include <Utils/NetworkHelper.h>
#include <PluginManager.h>
#include <Tools/Utils.h>
#include <LiteLoader/Main/Version.h>
#include <string>
#include <filesystem>
#include <map>
using namespace std;
//////////////////// Classes ////////////////////
ClassDefine<void> LlClassBuilder =
defineClass("ll")
.function("version", &LlClass::version)
.function("versionString", &LlClass::versionString)
.function("versionStatus", &LlClass::getVersionStatus)
.function("isDebugMode", &LlClass::isDebugMode)
.function("requireVersion", &LlClass::requireVersion)
.function("listPlugins", &LlClass::listPlugins)
.function("getAllPluginInfo", &LlClass::getAllPluginInfo)
.function("import", &LlClass::importFunc)
.function("export", &LlClass::exportFunc)
.function("hasExported", &LlClass::hasFuncExported)
.function("require", &LlClass::require)
.function("scriptEngineVersion", &LlClass::getScriptEngineVersion)
.function("eval", &LlClass::eval)
.function("registerPlugin", &LlClass::registerPlugin)
.function("getPluginInfo", &LlClass::getPluginInfo)
.function("checkVersion", &LlClass::requireVersion)
.property("language", &LlClass::getLanguage)
.build();
Local<Value> LlClass::registerPlugin(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
if (args.size() >= 2)
CHECK_ARG_TYPE(args[1], ValueKind::kString);
// if (args.size() >= 3)
// CHECK_ARG_TYPE(args[2], ValueKind::kObject);
if (args.size() >= 4)
CHECK_ARG_TYPE(args[3], ValueKind::kObject);
try {
string name = args[0].toStr();
string desc = args.size() >= 2 ? args[1].toStr() : "";
LL::Version ver = LL::Version(1, 0, 0);
if (args.size() >= 3) {
if (args[2].isArray()) {
Local<Array> verInfo = args[2].asArray();
if (verInfo.size() >= 1) {
Local<Value> major = verInfo.get(0);
if (major.isNumber())
ver.major = major.toInt();
}
if (verInfo.size() >= 2) {
Local<Value> minor = verInfo.get(1);
if (minor.isNumber())
ver.minor = minor.toInt();
}
if (verInfo.size() >= 3) {
Local<Value> revision = verInfo.get(2);
if (revision.isNumber())
ver.revision = revision.toInt();
}
} else if (args[2].isObject()) {
Local<Object> verInfo = args[2].asObject();
if (verInfo.has("major")) {
Local<Value> major = verInfo.get("major");
if (major.isNumber())
ver.major = major.toInt();
}
if (verInfo.has("minor")) {
Local<Value> minor = verInfo.get("minor");
if (minor.isNumber())
ver.minor = minor.toInt();
}
if (verInfo.has("revision")) {
Local<Value> revision = verInfo.get("revision");
if (revision.isNumber())
ver.revision = revision.toInt();
}
} else {
LOG_WRONG_ARG_TYPE();
return Boolean::newBoolean(false);
}
}
map<string, string> other;
if (args.size() >= 4) {
Local<Object> otherInfo = args[3].asObject();
auto keys = otherInfo.getKeyNames();
for (auto& key : keys) {
other[key] = otherInfo.get(key).toStr();
}
}
ENGINE_OWN_DATA()->pluginName = ENGINE_OWN_DATA()->logger.title = name;
return Boolean::newBoolean(PluginManager::registerPlugin(ENGINE_OWN_DATA()->pluginFileOrDirPath,
name, desc, ver, other));
}
CATCH("Fail in LLSERegisterPlugin!");
}
Local<Value> LlClass::getPluginInfo(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
std::string name = args[0].toStr();
auto plugin = LL::getPlugin(name);
if (plugin) {
auto result = Object::newObject();
result.set("name", plugin->name);
result.set("desc", plugin->desc);
auto ver = Array::newArray();
ver.add(Number::newNumber(plugin->version.major));
ver.add(Number::newNumber(plugin->version.minor));
ver.add(Number::newNumber(plugin->version.revision));
result.set("version", ver);
result.set("versionStr", plugin->version.toString(true));
result.set("filePath", plugin->filePath);
auto others = Object::newObject();
for (auto& [k, v] : plugin->others) {
others.set(k, v);
}
result.set("others", others);
return result;
}
return Local<Value>();
}
CATCH("Fail in getPluginInfo");
}
Local<Value> LlClass::getVersionStatus(const Arguments& args) {
try {
int versionStatusValue;
if (LITELOADER_VERSION_STATUS == LL::Version::Status::Release) {
versionStatusValue = 0;
} else if (LITELOADER_VERSION_STATUS == LL::Version::Status::Beta) {
versionStatusValue = 1;
} else if (LITELOADER_VERSION_STATUS == LL::Version::Status::Dev) {
versionStatusValue = 2;
}
return Number::newNumber(versionStatusValue);
}
CATCH("Fail in LLSEGetVersionStatus")
}
Local<Value> LlClass::version(const Arguments& args) {
try {
Local<Object> ver = Object::newObject();
ver.set("major", LITELOADER_VERSION_MAJOR);
ver.set("minor", LITELOADER_VERSION_MINOR);
ver.set("revision", LITELOADER_VERSION_REVISION);
ver.set("isBeta", LITELOADER_VERSION_STATUS == LL::Version::Status::Beta);
ver.set("isRelease", LITELOADER_VERSION_STATUS == LL::Version::Status::Release);
ver.set("isDev", LITELOADER_VERSION_STATUS == LL::Version::Status::Dev);
return ver;
}
CATCH("Fail in LLSEGetVersion!")
}
Local<Value> LlClass::getLanguage() {
try {
return String::newString(PluginOwnData::getImpl<I18nBase>(LL::getLoaderHandle(), I18nBase::POD_KEY).defaultLocaleName);
}
CATCH("Fail in LLSEGetLanguage")
}
Local<Value> LlClass::isDebugMode(const Arguments& args) {
try {
return Boolean::newBoolean(LL::isDebugMode());
}
CATCH("Fail in LLSEGetIsDebugMode")
}
Local<Value> LlClass::versionString(const Arguments& args) {
try {
return String::newString(LL::getLoaderVersionString());
}
CATCH("Fail in LLSEGetVersionString!")
}
Local<Value> LlClass::requireVersion(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
if (args.size() >= 2)
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
if (args.size() >= 3)
CHECK_ARG_TYPE(args[2], ValueKind::kNumber);
try {
return Boolean::newBoolean(!IsVersionLess(LITELOADER_VERSION_MAJOR, LITELOADER_VERSION_MINOR, LITELOADER_VERSION_REVISION,
args[0].toInt(), (args.size() >= 2) ? args[1].toInt() : 0, (args.size() >= 3) ? args[2].toInt() : 0));
}
CATCH("Fail in LLSERequireVersion!")
}
Local<Value> LlClass::getAllPluginInfo(const Arguments& args) {
try {
Local<Array> plugins = Array::newArray();
auto list = PluginManager::getAllPlugins();
for (auto& plugin : list) {
// Create plugin object
auto pluginObject = Object::newObject();
pluginObject.set("name", plugin.second->name);
pluginObject.set("desc", plugin.second->desc);
auto ver = Array::newArray();
ver.add(Number::newNumber(plugin.second->version.major));
ver.add(Number::newNumber(plugin.second->version.minor));
ver.add(Number::newNumber(plugin.second->version.revision));
pluginObject.set("version", ver);
pluginObject.set("versionStr", plugin.second->version.toString(true));
pluginObject.set("filePath", plugin.second->filePath);
auto others = Object::newObject();
for (auto& [k, v] : plugin.second->others) {
others.set(k, v);
}
pluginObject.set("others", others);
// Add plugin object to list
plugins.add(pluginObject);
}
return plugins;
}
CATCH("Fail in LLSEGetAllPluginInfo!")
}
// For Compatibility
Local<Value> LlClass::listPlugins(const Arguments& args) {
try {
Local<Array> plugins = Array::newArray();
auto list = PluginManager::getAllPlugins();
for (auto& plugin : list) {
plugins.add(String::newString(plugin.second->name));
}
return plugins;
}
CATCH("Fail in LLSEListPlugins!")
}
Local<Value> LlClass::require(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1)
CHECK_ARG_TYPE(args[0], ValueKind::kString)
if (args.size() >= 2)
CHECK_ARG_TYPE(args[1], ValueKind::kString)
try {
bool existing = false;
string require = args[0].toStr();
string thisName = ENGINE_OWN_DATA()->pluginName;
//已加载插件
if (PluginManager::getPlugin(require) != nullptr) {
logger.info(tr("llse.api.ll.require.success", thisName, require));
return Boolean::newBoolean(true);
}
//插件目录
existing = false;
string requirePath = "";
// Direct
std::error_code ec;
if (filesystem::exists(str2wstr(require), ec)) {
requirePath = require;
existing = true;
} else {
auto list = GetFileNameList(LLSE_PLUGINS_LOAD_DIR);
for (auto fileName : list) {
if (fileName == require) {
requirePath = string(LLSE_PLUGINS_LOAD_DIR) + "/" + require;
existing = true;
break;
}
}
}
if (existing) {
bool success = PluginManager::loadPlugin(requirePath);
if (success) {
logger.info(thisName + tr("llseapi.require.success") + require);
return Boolean::newBoolean(true);
} else {
logger.error(thisName + tr("llseapi.require.fail"));
return Boolean::newBoolean(false);
}
}
//依赖库目录
existing = false;
auto list = GetFileNameList(LLSE_DEPENDS_DIR);
for (auto fileName : list) {
if (fileName == require) {
existing = true;
break;
}
}
if (existing) {
bool success = PluginManager::loadPlugin(string(LLSE_DEPENDS_DIR) + "/" + require);
if (success) {
logger.info(thisName + tr("llseapi.require.success") + require);
return Boolean::newBoolean(true);
} else {
logger.error(thisName + tr("llseapi.require.fail"));
return Boolean::newBoolean(false);
}
}
// HTTP(s)下载
if (args.size() == 1) {
logger.error(thisName + tr("llseapi.require.fail"));
return Boolean::newBoolean(false);
}
string remotePath = args[1].toStr();
int status;
string result, downloadPath = string(LLSE_DEPENDS_DIR) + "/" + require;
if (!HttpGetSync(remotePath, &status, &result) || status != 200) {
logger.error(thisName + tr("llseapi.require.network.fail") + to_string(status));
return Boolean::newBoolean(false);
}
WriteAllFile(downloadPath, result, false);
logger.info(thisName + tr("llseapi.require.download.success") + downloadPath);
//下载完毕安装
bool success = PluginManager::loadPlugin(downloadPath);
if (success) {
logger.info(thisName + tr("llseapi.require.success") + require);
return Boolean::newBoolean(true);
} else {
logger.error(thisName + tr("llseapi.require.fail"));
return Boolean::newBoolean(false);
}
}
CATCH("Fail in LLSERequire!")
}
Local<Value> LlClass::getScriptEngineVersion(const Arguments& args) {
try {
return String::newString(EngineScope::currentEngine()->getEngineVersion());
}
CATCH("Fail in LLSEGetScriptEngineVerison")
}
Local<Value> LlClass::eval(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
return EngineScope::currentEngine()->eval(args[0].toStr());
}
CATCH("Fail in LLSEEval!")
}