#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"; } }