mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-06 20:03:51 +00:00
537 lines
18 KiB
C++
537 lines
18 KiB
C++
#include <iostream>
|
||
#include <string>
|
||
#include <vector>
|
||
#include <memory>
|
||
#include <cmath>
|
||
#include <sstream>
|
||
|
||
#include <API/BaseAPI.h>
|
||
#include <API/BlockAPI.h>
|
||
#include <API/EntityAPI.h>
|
||
#include <API/ItemAPI.h>
|
||
#include <API/PlayerAPI.h>
|
||
#include <API/DeviceAPI.h>
|
||
#include <API/ItemAPI.h>
|
||
#include <API/EntityAPI.h>
|
||
#include <API/ContainerAPI.h>
|
||
#include <API/NbtAPI.h>
|
||
#include <API/GuiAPI.h>
|
||
#include <API/DataAPI.h>
|
||
#include <API/DatabaseAPI.h>
|
||
#include <API/PlayerAPI.h>
|
||
#include <API/NetworkAPI.h>
|
||
#include <Global.hpp>
|
||
#include <Engine/EngineOwnData.h>
|
||
#include "APIHelp.h"
|
||
|
||
#include "NativeAPI.h"
|
||
|
||
using namespace std;
|
||
|
||
//////////////////// APIs ////////////////////
|
||
template <typename T>
|
||
void PrintValue(T& out, Local<Value> v) {
|
||
switch (v.getKind()) {
|
||
case ValueKind::kString:
|
||
out << v.asString().toString();
|
||
break;
|
||
case ValueKind::kNumber:
|
||
if (CheckIsFloat(v))
|
||
out << v.asNumber().toDouble();
|
||
else
|
||
out << v.asNumber().toInt64();
|
||
break;
|
||
case ValueKind::kBoolean:
|
||
out << v.asBoolean().value();
|
||
break;
|
||
case ValueKind::kNull:
|
||
out << "<Null>";
|
||
break;
|
||
case ValueKind::kArray: {
|
||
Local<Array> arr = v.asArray();
|
||
if (arr.size() == 0)
|
||
out << "[]";
|
||
else {
|
||
static std::vector<Local<Array>> arrStack = {};
|
||
if (std::find(arrStack.begin(), arrStack.end(), arr) == arrStack.end()) {
|
||
arrStack.push_back(arr);
|
||
out << '[';
|
||
PrintValue(out, arr.get(0));
|
||
for (int i = 1; i < arr.size(); ++i) {
|
||
out << ',';
|
||
PrintValue(out, arr.get(i));
|
||
}
|
||
out << ']';
|
||
arrStack.pop_back();
|
||
} else {
|
||
out << "<Recursive Array>";
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case ValueKind::kObject: {
|
||
// 自定义类型也会被识别为Object,优先处理
|
||
// IntPos
|
||
IntPos* intpos = IntPos::extractPos(v);
|
||
if (intpos != nullptr) {
|
||
out << DimId2Name(intpos->dim) << "(" << intpos->x << "," << intpos->y << "," << intpos->z << ")";
|
||
break;
|
||
}
|
||
|
||
// FloatPos
|
||
FloatPos* floatpos = FloatPos::extractPos(v);
|
||
if (floatpos != nullptr) {
|
||
out << fixed << setprecision(2) << DimId2Name(floatpos->dim) << "(" << floatpos->x << "," << floatpos->y << "," << floatpos->z << ")";
|
||
break;
|
||
}
|
||
|
||
// 其他自定义类型
|
||
if (IsInstanceOf<NativePointer>(v)) {
|
||
std::stringstream ss;
|
||
ss << std::hex << (intptr_t)EngineScope::currentEngine()->getNativeInstance<NativePointer>(v)->get();
|
||
out << ss.str();
|
||
break;
|
||
}
|
||
if (IsInstanceOf<ScriptNativeFunction>(v)) {
|
||
std::stringstream ss;
|
||
ScriptNativeFunction* func = EngineScope::currentEngine()->getNativeInstance<ScriptNativeFunction>(v);
|
||
ss << std::hex
|
||
<< "Address: " << (intptr_t)func->mFunction << " "
|
||
<< "Symbol: " << func->mSymbol << " "
|
||
<< "ReturnType: " << magic_enum::enum_name(func->mReturnVal) << " "
|
||
<< "Params: " << func->mParams.size();
|
||
for (size_t i = 0; i < func->mParams.size(); ++i) {
|
||
ss << " [" << i << "]" << magic_enum::enum_name(func->mParams[i]);
|
||
}
|
||
|
||
out << ss.str();
|
||
break;
|
||
}
|
||
if (IsInstanceOf<BlockClass>(v)) {
|
||
out << "<Block>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<KVDBClass>(v)) {
|
||
out << "<Database>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<ConfJsonClass>(v)) {
|
||
out << "<ConfJson>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<ConfIniClass>(v)) {
|
||
out << "<ConfIni>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<DeviceClass>(v)) {
|
||
out << "<DeviceInfo>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<ContainerClass>(v)) {
|
||
out << "<Container>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<EntityClass>(v)) {
|
||
out << "<Entity>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<SimpleFormClass>(v)) {
|
||
out << "<SimpleForm>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<CustomFormClass>(v)) {
|
||
out << "<CustomForm>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<ItemClass>(v)) {
|
||
out << "<Item>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<PlayerClass>(v)) {
|
||
out << "<Player>";
|
||
break;
|
||
}
|
||
if (IsNbtClass(v)) {
|
||
out << "<NbtClass>";
|
||
break;
|
||
}
|
||
if (IsInstanceOf<DBSessionClass>(v)) {
|
||
out << "<DBSession>";
|
||
}
|
||
if (IsInstanceOf<DBStmtClass>(v)) {
|
||
out << "<DBStmt>";
|
||
}
|
||
if (IsInstanceOf<HttpServerClass>(v)) {
|
||
out << "<HttpServer>";
|
||
}
|
||
if (IsInstanceOf<HttpRequestClass>(v)) {
|
||
out << "<HttpRequest>";
|
||
}
|
||
if (IsInstanceOf<HttpResponseClass>(v)) {
|
||
out << "<HttpResponse>";
|
||
}
|
||
|
||
Local<Object> obj = v.asObject();
|
||
std::vector<std::string> keys = obj.getKeyNames();
|
||
if (keys.empty())
|
||
out << "{}";
|
||
else {
|
||
static std::vector<Local<Object>> objStack = {};
|
||
if (std::find(objStack.begin(), objStack.end(), obj) == objStack.end()) {
|
||
objStack.push_back(obj);
|
||
out << '{';
|
||
out << keys[0] + ":";
|
||
PrintValue(out, obj.get(keys[0]));
|
||
for (int i = 1; i < keys.size(); ++i) {
|
||
out << "," + keys[i] + ":";
|
||
PrintValue(out, obj.get(keys[i]));
|
||
}
|
||
out << '}';
|
||
objStack.pop_back();
|
||
} else {
|
||
out << "<Recursive Object>";
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case ValueKind::kByteBuffer: {
|
||
Local<ByteBuffer> bytes = v.asByteBuffer();
|
||
out << ((const char*)bytes.getRawBytes(), bytes.byteLength());
|
||
break;
|
||
}
|
||
case ValueKind::kFunction: {
|
||
out << "<Function>";
|
||
break;
|
||
}
|
||
default: {
|
||
out << "<Unknown>";
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
std::string ValueToString(Local<Value> v) {
|
||
std::ostringstream sout;
|
||
PrintValue(sout, v);
|
||
return sout.str();
|
||
}
|
||
|
||
bool CheckIsFloat(const Local<Value>& num) {
|
||
try {
|
||
return fabs(num.asNumber().toDouble() - num.asNumber().toInt64()) >= 1e-15;
|
||
} catch (...) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
///////////////////// Json To Value /////////////////////
|
||
|
||
Local<Value> BigInteger_Helper(fifo_json& i) {
|
||
if (i.is_number_integer()) {
|
||
if (i.is_number_unsigned()) {
|
||
auto ui = i.get<uint64_t>();
|
||
if (ui <= LLONG_MAX)
|
||
return Number::newNumber((int64_t)ui);
|
||
return Number::newNumber((double)ui);
|
||
}
|
||
return Number::newNumber(i.get<int64_t>());
|
||
}
|
||
return Local<Value>();
|
||
}
|
||
|
||
void JsonToValue_Helper(Local<Array>& res, fifo_json& j);
|
||
|
||
void JsonToValue_Helper(Local<Object>& res, const string& key, fifo_json& j) {
|
||
switch (j.type()) {
|
||
case fifo_json::value_t::string:
|
||
res.set(key, String::newString(j.get<string>()));
|
||
break;
|
||
case fifo_json::value_t::number_integer:
|
||
case fifo_json::value_t::number_unsigned:
|
||
res.set(key, BigInteger_Helper(j));
|
||
break;
|
||
case fifo_json::value_t::number_float:
|
||
res.set(key, Number::newNumber(j.get<double>()));
|
||
break;
|
||
case fifo_json::value_t::boolean:
|
||
res.set(key, Boolean::newBoolean(j.get<bool>()));
|
||
break;
|
||
case fifo_json::value_t::null:
|
||
res.set(key, Local<Value>());
|
||
break;
|
||
case fifo_json::value_t::array: {
|
||
Local<Array> arrToAdd = Array::newArray();
|
||
for (fifo_json::iterator it = j.begin(); it != j.end(); ++it)
|
||
JsonToValue_Helper(arrToAdd, *it);
|
||
res.set(key, arrToAdd);
|
||
break;
|
||
}
|
||
case fifo_json::value_t::object: {
|
||
Local<Object> objToAdd = Object::newObject();
|
||
for (fifo_json::iterator it = j.begin(); it != j.end(); ++it)
|
||
JsonToValue_Helper(objToAdd, it.key(), it.value());
|
||
res.set(key, objToAdd);
|
||
break;
|
||
}
|
||
default:
|
||
res.set(key, Local<Value>());
|
||
break;
|
||
}
|
||
}
|
||
|
||
void JsonToValue_Helper(Local<Array>& res, fifo_json& j) {
|
||
switch (j.type()) {
|
||
case fifo_json::value_t::string:
|
||
res.add(String::newString(j.get<string>()));
|
||
break;
|
||
case fifo_json::value_t::number_integer:
|
||
case fifo_json::value_t::number_unsigned:
|
||
res.add(BigInteger_Helper(j));
|
||
break;
|
||
case fifo_json::value_t::number_float:
|
||
res.add(Number::newNumber(j.get<double>()));
|
||
break;
|
||
case fifo_json::value_t::boolean:
|
||
res.add(Boolean::newBoolean(j.get<bool>()));
|
||
break;
|
||
case fifo_json::value_t::null:
|
||
res.add(Local<Value>());
|
||
break;
|
||
case fifo_json::value_t::array: {
|
||
Local<Array> arrToAdd = Array::newArray();
|
||
for (fifo_json::iterator it = j.begin(); it != j.end(); ++it)
|
||
JsonToValue_Helper(arrToAdd, *it);
|
||
res.add(arrToAdd);
|
||
break;
|
||
}
|
||
case fifo_json::value_t::object: {
|
||
Local<Object> objToAdd = Object::newObject();
|
||
for (fifo_json::iterator it = j.begin(); it != j.end(); ++it)
|
||
JsonToValue_Helper(objToAdd, it.key(), it.value());
|
||
res.add(objToAdd);
|
||
break;
|
||
}
|
||
default:
|
||
res.add(Local<Value>());
|
||
break;
|
||
}
|
||
}
|
||
|
||
Local<Value> JsonToValue(fifo_json j) {
|
||
Local<Value> res;
|
||
|
||
switch (j.type()) {
|
||
case fifo_json::value_t::string:
|
||
res = String::newString(j.get<string>());
|
||
break;
|
||
case fifo_json::value_t::number_integer:
|
||
case fifo_json::value_t::number_unsigned:
|
||
res = BigInteger_Helper(j);
|
||
break;
|
||
case fifo_json::value_t::number_float:
|
||
res = Number::newNumber(j.get<double>());
|
||
break;
|
||
case fifo_json::value_t::boolean:
|
||
res = Boolean::newBoolean(j.get<bool>());
|
||
break;
|
||
case fifo_json::value_t::null:
|
||
res = Local<Value>();
|
||
break;
|
||
case fifo_json::value_t::array: {
|
||
Local<Array> resArr = Array::newArray();
|
||
for (fifo_json::iterator it = j.begin(); it != j.end(); ++it)
|
||
JsonToValue_Helper(resArr, *it);
|
||
res = resArr;
|
||
break;
|
||
}
|
||
case fifo_json::value_t::object: {
|
||
Local<Object> resObj = Object::newObject();
|
||
for (fifo_json::iterator it = j.begin(); it != j.end(); ++it)
|
||
JsonToValue_Helper(resObj, it.key(), it.value());
|
||
res = resObj;
|
||
break;
|
||
}
|
||
default:
|
||
res = Local<Value>();
|
||
break;
|
||
}
|
||
|
||
return res;
|
||
}
|
||
|
||
Local<Value> JsonToValue(std::string jsonStr) {
|
||
try {
|
||
if (jsonStr.empty())
|
||
return String::newString("");
|
||
if (jsonStr.front() == '\"' && jsonStr.back() == '\"')
|
||
return String::newString(jsonStr.substr(1, jsonStr.size() - 2));
|
||
auto j = fifo_json::parse(jsonStr, nullptr, true, true);
|
||
return JsonToValue(j);
|
||
} catch (const fifo_json::exception& e) {
|
||
logger.warn(tr("llse.apiHelp.parseJson.fail") + TextEncoding::toUTF8(e.what()));
|
||
return String::newString(jsonStr);
|
||
}
|
||
}
|
||
|
||
|
||
///////////////////// Value To Json /////////////////////
|
||
|
||
void ValueToJson_Obj_Helper(fifo_json& res, const Local<Object>& v);
|
||
|
||
void ValueToJson_Arr_Helper(fifo_json& res, const Local<Array>& v) {
|
||
for (int i = 0; i < v.size(); ++i) {
|
||
switch (v.get(i).getKind()) {
|
||
case ValueKind::kString:
|
||
res.push_back(v.get(i).asString().toString());
|
||
break;
|
||
case ValueKind::kNumber:
|
||
if (CheckIsFloat(v.get(i)))
|
||
res.push_back(v.get(i).asNumber().toDouble());
|
||
else
|
||
res.push_back(v.get(i).asNumber().toInt64());
|
||
break;
|
||
case ValueKind::kBoolean:
|
||
res.push_back(v.get(i).asBoolean().value());
|
||
break;
|
||
case ValueKind::kNull:
|
||
res.push_back(nullptr);
|
||
break;
|
||
case ValueKind::kArray: {
|
||
Local<Array> arrToAdd = v.get(i).asArray();
|
||
if (arrToAdd.size() == 0)
|
||
res.push_back(fifo_json::array());
|
||
else {
|
||
fifo_json arrJson = fifo_json::array();
|
||
ValueToJson_Arr_Helper(arrJson, arrToAdd);
|
||
res.push_back(arrJson);
|
||
}
|
||
break;
|
||
}
|
||
case ValueKind::kObject: {
|
||
Local<Object> objToAdd = v.get(i).asObject();
|
||
if (objToAdd.getKeyNames().empty())
|
||
res.push_back(fifo_json::object());
|
||
else {
|
||
fifo_json objJson = fifo_json::object();
|
||
ValueToJson_Obj_Helper(objJson, objToAdd);
|
||
res.push_back(objJson);
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
res.push_back(nullptr);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ValueToJson_Obj_Helper(fifo_json& res, const Local<Object>& v) {
|
||
auto keys = v.getKeyNames();
|
||
for (auto& key : keys) {
|
||
switch (v.get(key).getKind()) {
|
||
case ValueKind::kString:
|
||
res.push_back({key, v.get(key).asString().toString()});
|
||
break;
|
||
case ValueKind::kNumber:
|
||
if (CheckIsFloat(v.get(key)))
|
||
res.push_back({key, v.get(key).asNumber().toDouble()});
|
||
else
|
||
res.push_back({key, v.get(key).asNumber().toInt64()});
|
||
break;
|
||
case ValueKind::kBoolean:
|
||
res.push_back({key, v.get(key).asBoolean().value()});
|
||
break;
|
||
case ValueKind::kNull:
|
||
res.push_back({key, nullptr});
|
||
break;
|
||
case ValueKind::kArray: {
|
||
Local<Array> arrToAdd = v.get(key).asArray();
|
||
if (arrToAdd.size() == 0)
|
||
res.push_back({key, fifo_json::array()});
|
||
else {
|
||
fifo_json arrJson = fifo_json::array();
|
||
ValueToJson_Arr_Helper(arrJson, arrToAdd);
|
||
res.push_back({key, arrJson});
|
||
}
|
||
break;
|
||
}
|
||
case ValueKind::kObject: {
|
||
Local<Object> objToAdd = v.get(key).asObject();
|
||
if (objToAdd.getKeyNames().empty())
|
||
res.push_back({key, fifo_json::object()});
|
||
else {
|
||
fifo_json objJson = fifo_json::object();
|
||
ValueToJson_Obj_Helper(objJson, objToAdd);
|
||
res.push_back({key, objJson});
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
res.push_back({key, nullptr});
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
std::string ValueToJson(Local<Value> v, int formatIndent) {
|
||
string result;
|
||
switch (v.getKind()) {
|
||
case ValueKind::kString:
|
||
result = "\"" + v.asString().toString() + "\"";
|
||
ReplaceStr(result, "\n", "\\n");
|
||
break;
|
||
case ValueKind::kNumber:
|
||
if (CheckIsFloat(v)) {
|
||
result = std::to_string(v.asNumber().toDouble());
|
||
} else {
|
||
result = std::to_string(v.asNumber().toInt64());
|
||
}
|
||
break;
|
||
case ValueKind::kBoolean:
|
||
result = std::to_string(v.asBoolean().value());
|
||
break;
|
||
case ValueKind::kNull:
|
||
result = "";
|
||
break;
|
||
case ValueKind::kArray: {
|
||
fifo_json jsonRes = fifo_json::array();
|
||
ValueToJson_Arr_Helper(jsonRes, v.asArray());
|
||
result = jsonRes.dump(formatIndent);
|
||
break;
|
||
}
|
||
case ValueKind::kObject: {
|
||
fifo_json jsonRes = fifo_json::object();
|
||
ValueToJson_Obj_Helper(jsonRes, v.asObject());
|
||
result = jsonRes.dump(formatIndent);
|
||
break;
|
||
}
|
||
default:
|
||
result = "";
|
||
break;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
std::string ValueKindToString(const ValueKind& kind) {
|
||
switch (kind) {
|
||
case ValueKind::kString:
|
||
return "string";
|
||
case ValueKind::kNumber:
|
||
return "number";
|
||
case ValueKind::kBoolean:
|
||
return "boolean";
|
||
case ValueKind::kNull:
|
||
return "null";
|
||
case ValueKind::kObject:
|
||
return "object";
|
||
case ValueKind::kArray:
|
||
return "array";
|
||
case ValueKind::kFunction:
|
||
return "function";
|
||
case ValueKind::kByteBuffer:
|
||
return "bytebuffer";
|
||
default:
|
||
return "unknown";
|
||
}
|
||
} |