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

2160 lines
73 KiB
C++

#include "APIHelp.h"
#include "NbtAPI.h"
#include <vector>
#include <string>
#include "ItemAPI.h"
#include "BlockAPI.h"
#include <MC/EndTag.hpp>
#include <MC/ByteTag.hpp>
#include <MC/ShortTag.hpp>
#include <MC/IntTag.hpp>
#include <MC/Int64Tag.hpp>
#include <MC/FloatTag.hpp>
#include <MC/DoubleTag.hpp>
#include <MC/ByteArrayTag.hpp>
#include <MC/StringTag.hpp>
#include <MC/ListTag.hpp>
#include <MC/CompoundTag.hpp>
using namespace std;
//////////////////// Class Definition ////////////////////
ClassDefine<void> NbtStaticBuilder =
defineClass("NBT")
.function("parseSNBT", &NbtStatic::parseSNBT)
.function("parseBinaryNBT", &NbtStatic::parseBinaryNBT)
.property("End", &NbtStatic::getType<Tag::Type::End>)
.property("Byte", &NbtStatic::getType<Tag::Type::Byte>)
.property("Short", &NbtStatic::getType<Tag::Type::Short>)
.property("Int", &NbtStatic::getType<Tag::Type::Int>)
.property("Long", &NbtStatic::getType<Tag::Type::Int64>)
.property("Float", &NbtStatic::getType<Tag::Type::Float>)
.property("Double", &NbtStatic::getType<Tag::Type::Double>)
.property("ByteArray", &NbtStatic::getType<Tag::Type::ByteArray>)
.property("String", &NbtStatic::getType<Tag::Type::String>)
.property("List", &NbtStatic::getType<Tag::Type::List>)
.property("Compound", &NbtStatic::getType<Tag::Type::Compound>)
// For Compatibility
.function("createTag", &NbtStatic::newTag)
.function("newTag", &NbtStatic::newTag)
.build();
ClassDefine<NbtEndClass> NbtEndClassBuilder =
defineClass<NbtEndClass>("NbtEnd")
.constructor(&NbtEndClass::constructor)
.instanceFunction("getType", &NbtEndClass::getType)
.instanceFunction("toString", &NbtEndClass::toString)
.instanceFunction("set", &NbtEndClass::set)
.instanceFunction("get", &NbtEndClass::get)
.build();
ClassDefine<NbtByteClass> NbtByteClassBuilder =
defineClass<NbtByteClass>("NbtByte")
.constructor(&NbtByteClass::constructor)
.instanceFunction("getType", &NbtByteClass::getType)
.instanceFunction("toString", &NbtByteClass::toString)
.instanceFunction("set", &NbtByteClass::set)
.instanceFunction("get", &NbtByteClass::get)
.build();
ClassDefine<NbtShortClass> NbtShortClassBuilder =
defineClass<NbtShortClass>("NbtShort")
.constructor(&NbtShortClass::constructor)
.instanceFunction("getType", &NbtShortClass::getType)
.instanceFunction("toString", &NbtShortClass::toString)
.instanceFunction("set", &NbtShortClass::set)
.instanceFunction("get", &NbtShortClass::get)
.build();
ClassDefine<NbtIntClass> NbtIntClassBuilder =
defineClass<NbtIntClass>("NbtInt")
.constructor(&NbtIntClass::constructor)
.instanceFunction("getType", &NbtIntClass::getType)
.instanceFunction("toString", &NbtIntClass::toString)
.instanceFunction("set", &NbtIntClass::set)
.instanceFunction("get", &NbtIntClass::get)
.build();
ClassDefine<NbtLongClass> NbtLongClassBuilder =
defineClass<NbtLongClass>("NbtLong")
.constructor(&NbtLongClass::constructor)
.instanceFunction("getType", &NbtLongClass::getType)
.instanceFunction("toString", &NbtLongClass::toString)
.instanceFunction("set", &NbtLongClass::set)
.instanceFunction("get", &NbtLongClass::get)
.build();
ClassDefine<NbtFloatClass> NbtFloatClassBuilder =
defineClass<NbtFloatClass>("NbtFloat")
.constructor(&NbtFloatClass::constructor)
.instanceFunction("getType", &NbtFloatClass::getType)
.instanceFunction("toString", &NbtFloatClass::toString)
.instanceFunction("set", &NbtFloatClass::set)
.instanceFunction("get", &NbtFloatClass::get)
.build();
ClassDefine<NbtDoubleClass> NbtDoubleClassBuilder =
defineClass<NbtDoubleClass>("NbtDouble")
.constructor(&NbtDoubleClass::constructor)
.instanceFunction("getType", &NbtDoubleClass::getType)
.instanceFunction("toString", &NbtDoubleClass::toString)
.instanceFunction("set", &NbtDoubleClass::set)
.instanceFunction("get", &NbtDoubleClass::get)
.build();
ClassDefine<NbtStringClass> NbtStringClassBuilder =
defineClass<NbtStringClass>("NbtString")
.constructor(&NbtStringClass::constructor)
.instanceFunction("getType", &NbtStringClass::getType)
.instanceFunction("toString", &NbtStringClass::toString)
.instanceFunction("set", &NbtStringClass::set)
.instanceFunction("get", &NbtStringClass::get)
.build();
ClassDefine<NbtByteArrayClass> NbtByteArrayClassBuilder =
defineClass<NbtByteArrayClass>("NbtByteArray")
.constructor(&NbtByteArrayClass::constructor)
.instanceFunction("getType", &NbtByteArrayClass::getType)
.instanceFunction("toString", &NbtByteArrayClass::toString)
.instanceFunction("set", &NbtByteArrayClass::set)
.instanceFunction("get", &NbtByteArrayClass::get)
.build();
ClassDefine<NbtListClass> NbtListClassBuilder =
defineClass<NbtListClass>("NbtList")
.constructor(&NbtListClass::constructor)
.instanceFunction("getType", &NbtListClass::getType)
.instanceFunction("toString", &NbtListClass::toString)
.instanceFunction("getSize", &NbtListClass::getSize)
.instanceFunction("getTypeOf", &NbtListClass::getTypeOf)
.instanceFunction("setEnd", &NbtListClass::setEnd)
.instanceFunction("setByte", &NbtListClass::setByte)
.instanceFunction("setInt", &NbtListClass::setInt)
.instanceFunction("setShort", &NbtListClass::setShort)
.instanceFunction("setLong", &NbtListClass::setLong)
.instanceFunction("setFloat", &NbtListClass::setFloat)
.instanceFunction("setDouble", &NbtListClass::setDouble)
.instanceFunction("setString", &NbtListClass::setString)
.instanceFunction("setByteArray", &NbtListClass::setByteArray)
.instanceFunction("setTag", &NbtListClass::setTag)
.instanceFunction("addTag", &NbtListClass::addTag)
.instanceFunction("removeTag", &NbtListClass::removeTag)
.instanceFunction("getData", &NbtListClass::getData)
.instanceFunction("getTag", &NbtListClass::getTag)
.instanceFunction("toArray", &NbtListClass::toArray)
.build();
ClassDefine<NbtCompoundClass> NbtCompoundClassBuilder =
defineClass<NbtCompoundClass>("NbtCompound")
.constructor(&NbtCompoundClass::constructor)
.instanceFunction("getType", &NbtCompoundClass::getType)
.instanceFunction("toString", &NbtCompoundClass::toString)
.instanceFunction("getKeys", &NbtCompoundClass::getKeys)
.instanceFunction("getTypeOf", &NbtCompoundClass::getTypeOf)
.instanceFunction("setEnd", &NbtCompoundClass::setEnd)
.instanceFunction("setByte", &NbtCompoundClass::setByte)
.instanceFunction("setInt", &NbtCompoundClass::setInt)
.instanceFunction("setShort", &NbtCompoundClass::setShort)
.instanceFunction("setLong", &NbtCompoundClass::setLong)
.instanceFunction("setFloat", &NbtCompoundClass::setFloat)
.instanceFunction("setDouble", &NbtCompoundClass::setDouble)
.instanceFunction("setString", &NbtCompoundClass::setString)
.instanceFunction("setByteArray", &NbtCompoundClass::setByteArray)
.instanceFunction("setTag", &NbtCompoundClass::setTag)
.instanceFunction("removeTag", &NbtCompoundClass::removeTag)
.instanceFunction("getData", &NbtCompoundClass::getData)
.instanceFunction("getTag", &NbtCompoundClass::getTag)
.instanceFunction("toObject", &NbtCompoundClass::toObject)
.instanceFunction("toSNBT", &NbtCompoundClass::toSNBT)
.instanceFunction("toBinaryNBT", &NbtCompoundClass::toBinaryNBT)
.instanceFunction("destroy", &NbtCompoundClass::destroy)
.build();
//////////////////// Classes NbtEnd ////////////////////
NbtEndClass::NbtEndClass(const Local<Object>& scriptObj, std::unique_ptr<EndTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtEndClass::NbtEndClass(std::unique_ptr<EndTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtEndClass>{}) {
this->nbt = std::move(p);
}
NbtEndClass* NbtEndClass::constructor(const Arguments& args) {
try {
auto tag = EndTag::create();
return new NbtEndClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create EndTag!");
}
EndTag* NbtEndClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtEndClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtEndClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtEndClass::pack(EndTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<EndTag> nbt(tag);
auto* nbtObj = new NbtEndClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtEndClass(Tag::asTypedTag<EndTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtEnd!");
}
Local<Value> NbtEndClass::pack(std::unique_ptr<EndTag> tag) {
try {
return (new NbtEndClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtEnd!");
}
Local<Value> NbtEndClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::End);
}
Local<Value> NbtEndClass::get(const Arguments& args) {
try {
return Local<Value>();
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtEndClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtEndClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1)
try {
return Boolean::newBoolean(true);
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtByte ////////////////////
NbtByteClass::NbtByteClass(const Local<Object>& scriptObj, std::unique_ptr<ByteTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtByteClass::NbtByteClass(std::unique_ptr<ByteTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtByteClass>{}) {
this->nbt = std::move(p);
}
NbtByteClass* NbtByteClass::constructor(const Arguments& args) {
try {
auto tag = ByteTag::create((char)args[0].toInt());
return new NbtByteClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create ByteTag!");
}
ByteTag* NbtByteClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtByteClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtByteClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtByteClass::pack(ByteTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<ByteTag> nbt(tag);
auto* nbtObj = new NbtByteClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtByteClass(Tag::asTypedTag<ByteTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtByte!");
}
Local<Value> NbtByteClass::pack(std::unique_ptr<ByteTag> tag) {
try {
return (new NbtByteClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtByte!");
}
Local<Value> NbtByteClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Byte);
}
Local<Value> NbtByteClass::get(const Arguments& args) {
try {
return Number::newNumber(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtByteClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtByteClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
return Boolean::newBoolean(nbt->set((char)args[0].toInt()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtInt ////////////////////
NbtIntClass::NbtIntClass(const Local<Object>& scriptObj, std::unique_ptr<IntTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtIntClass::NbtIntClass(std::unique_ptr<IntTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtIntClass>{}) {
this->nbt = std::move(p);
}
NbtIntClass* NbtIntClass::constructor(const Arguments& args) {
try {
auto tag = IntTag::create(args[0].toInt());
return new NbtIntClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create IntTag!");
}
IntTag* NbtIntClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtIntClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtIntClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtIntClass::pack(IntTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<IntTag> nbt(tag);
auto* nbtObj = new NbtIntClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtIntClass(Tag::asTypedTag<IntTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtInt!");
}
Local<Value> NbtIntClass::pack(std::unique_ptr<IntTag> tag) {
try {
return (new NbtIntClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtInt!");
}
Local<Value> NbtIntClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Int);
}
Local<Value> NbtIntClass::get(const Arguments& args) {
try {
return Number::newNumber(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtIntClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtIntClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1)
try {
return Boolean::newBoolean(nbt->set(args[0].toInt()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtShort ////////////////////
NbtShortClass::NbtShortClass(const Local<Object>& scriptObj, std::unique_ptr<ShortTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtShortClass::NbtShortClass(std::unique_ptr<ShortTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtShortClass>{}) {
this->nbt = std::move(p);
}
NbtShortClass* NbtShortClass::constructor(const Arguments& args) {
try {
auto tag = ShortTag::create(args[0].toInt());
return new NbtShortClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create ShortTag!");
}
ShortTag* NbtShortClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtShortClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtShortClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtShortClass::pack(ShortTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<ShortTag> nbt(tag);
auto* nbtObj = new NbtShortClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtShortClass(Tag::asTypedTag<ShortTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtShort!");
}
Local<Value> NbtShortClass::pack(std::unique_ptr<ShortTag> tag) {
try {
return (new NbtShortClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtShort!");
}
Local<Value> NbtShortClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Short);
}
Local<Value> NbtShortClass::get(const Arguments& args) {
try {
return Number::newNumber(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtShortClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtShortClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
return Boolean::newBoolean(nbt->set(args[0].toInt()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtLong ////////////////////
NbtLongClass::NbtLongClass(const Local<Object>& scriptObj, std::unique_ptr<Int64Tag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtLongClass::NbtLongClass(std::unique_ptr<Int64Tag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtLongClass>{}) {
this->nbt = std::move(p);
}
NbtLongClass* NbtLongClass::constructor(const Arguments& args) {
try {
auto tag = Int64Tag::create(args[0].asNumber().toInt64());
return new NbtLongClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create LongTag!");
}
Int64Tag* NbtLongClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtLongClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtLongClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtLongClass::pack(Int64Tag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<Int64Tag> nbt(tag);
auto* nbtObj = new NbtLongClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtLongClass(Tag::asTypedTag<Int64Tag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtLong!");
}
Local<Value> NbtLongClass::pack(std::unique_ptr<Int64Tag> tag) {
try {
return (new NbtLongClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtLong!");
}
Local<Value> NbtLongClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Int64);
}
Local<Value> NbtLongClass::get(const Arguments& args) {
try {
return Number::newNumber(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtLongClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtLongClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
return Boolean::newBoolean(nbt->set(args[0].asNumber().toInt64()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtFloat ////////////////////
NbtFloatClass::NbtFloatClass(const Local<Object>& scriptObj, std::unique_ptr<FloatTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtFloatClass::NbtFloatClass(std::unique_ptr<FloatTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtFloatClass>{}) {
this->nbt = std::move(p);
}
NbtFloatClass* NbtFloatClass::constructor(const Arguments& args) {
try {
auto tag = FloatTag::create(args[0].asNumber().toFloat());
return new NbtFloatClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create FloatTag!");
}
FloatTag* NbtFloatClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtFloatClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtFloatClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtFloatClass::pack(FloatTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<FloatTag> nbt(tag);
auto* nbtObj = new NbtFloatClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtFloatClass(Tag::asTypedTag<FloatTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtFloat!");
}
Local<Value> NbtFloatClass::pack(std::unique_ptr<FloatTag> tag) {
try {
return (new NbtFloatClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtFloat!");
}
Local<Value> NbtFloatClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Float);
}
Local<Value> NbtFloatClass::get(const Arguments& args) {
try {
return Number::newNumber(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtFloatClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtFloatClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
return Boolean::newBoolean(nbt->set(args[0].asNumber().toFloat()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtDouble ////////////////////
NbtDoubleClass::NbtDoubleClass(const Local<Object>& scriptObj, std::unique_ptr<DoubleTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtDoubleClass::NbtDoubleClass(std::unique_ptr<DoubleTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtDoubleClass>{}) {
this->nbt = std::move(p);
}
NbtDoubleClass* NbtDoubleClass::constructor(const Arguments& args) {
try {
auto tag = DoubleTag::create(args[0].asNumber().toDouble());
return new NbtDoubleClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create DoubleTag!");
}
DoubleTag* NbtDoubleClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtDoubleClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtDoubleClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtDoubleClass::pack(DoubleTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<DoubleTag> nbt(tag);
auto* nbtObj = new NbtDoubleClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtDoubleClass(Tag::asTypedTag<DoubleTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtDouble!");
}
Local<Value> NbtDoubleClass::pack(std::unique_ptr<DoubleTag> tag) {
try {
return (new NbtDoubleClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtDouble!");
}
Local<Value> NbtDoubleClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Double);
}
Local<Value> NbtDoubleClass::get(const Arguments& args) {
try {
return Number::newNumber(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtDoubleClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtDoubleClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
return Boolean::newBoolean(nbt->set(args[0].asNumber().toDouble()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtString ////////////////////
NbtStringClass::NbtStringClass(const Local<Object>& scriptObj, std::unique_ptr<StringTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtStringClass::NbtStringClass(std::unique_ptr<StringTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtStringClass>{}) {
this->nbt = std::move(p);
}
NbtStringClass* NbtStringClass::constructor(const Arguments& args) {
try {
auto tag = StringTag::create(args[0].toStr());
return new NbtStringClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create StringTag!");
}
StringTag* NbtStringClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtStringClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtStringClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtStringClass::pack(StringTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<StringTag> nbt(tag);
auto* nbtObj = new NbtStringClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtStringClass(Tag::asTypedTag<StringTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtString!");
}
Local<Value> NbtStringClass::pack(std::unique_ptr<StringTag> tag) {
try {
return (new NbtStringClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtString!");
}
Local<Value> NbtStringClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::String);
}
Local<Value> NbtStringClass::get(const Arguments& args) {
try {
return String::newString(nbt->get());
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtStringClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtStringClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
return Boolean::newBoolean(nbt->set(args[0].toStr()));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtByteArray ////////////////////
NbtByteArrayClass::NbtByteArrayClass(const Local<Object>& scriptObj, std::unique_ptr<ByteArrayTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtByteArrayClass::NbtByteArrayClass(std::unique_ptr<ByteArrayTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtByteArrayClass>{}) {
this->nbt = std::move(p);
}
NbtByteArrayClass* NbtByteArrayClass::constructor(const Arguments& args) {
try {
auto buf = args[0].asByteBuffer();
auto tag = ByteArrayTag::create((char*)buf.getRawBytes(), buf.byteLength());
return new NbtByteArrayClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create ByteArrayTag!");
}
ByteArrayTag* NbtByteArrayClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtByteArrayClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtByteArrayClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtByteArrayClass::pack(ByteArrayTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<ByteArrayTag> nbt(tag);
auto* nbtObj = new NbtByteArrayClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtByteArrayClass(Tag::asTypedTag<ByteArrayTag>(tag->copy())))->getScriptObject();
}
CATCH("Fail in construct NbtByteArray!");
}
Local<Value> NbtByteArrayClass::pack(std::unique_ptr<ByteArrayTag> tag) {
try {
return (new NbtByteArrayClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtByteArray!");
}
Local<Value> NbtByteArrayClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::ByteArray);
}
Local<Value> NbtByteArrayClass::get(const Arguments& args) {
try {
auto& data = nbt->value();
return ByteBuffer::newByteBuffer(data.data.get(), data.size);
}
CATCH("Fail in NbtValueGet!")
}
Local<Value> NbtByteArrayClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtByteArrayClass::set(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
Local<ByteBuffer> buf = args[0].asByteBuffer();
return Boolean::newBoolean(nbt->set(TagMemoryChunk((char*)buf.getRawBytes(), buf.byteLength())));
}
CATCH("Fail in NbtValueSet!")
}
//////////////////// Classes NbtList ////////////////////
NbtListClass::NbtListClass(const Local<Object>& scriptObj, std::unique_ptr<ListTag> p)
: ScriptClass(scriptObj) {
this->nbt = std::move(p);
}
NbtListClass::NbtListClass(std::unique_ptr<ListTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtListClass>{}) {
this->nbt = std::move(p);
}
////////////////// Helper //////////////////
void NbtListClassAddHelper(ListTag* tag, Local<Array>& arr) {
if (arr.size() > 0) {
Local<Value> t = arr.get(0);
if (IsInstanceOf<NbtEndClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtEndClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtByteClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtByteClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtShortClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtShortClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtIntClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtIntClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtLongClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtLongClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtFloatClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtFloatClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtDoubleClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtDoubleClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtStringClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtStringClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtByteArrayClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtByteArrayClass::extract(arr.get(i))->copy());
else if (IsInstanceOf<NbtListClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtListClass::extract(arr.get(i))->copyList());
else if (IsInstanceOf<NbtCompoundClass>(t))
for (int i = 0; i < arr.size(); ++i)
tag->add(NbtCompoundClass::extract(arr.get(i))->clone());
else if (t.isArray()) {
for (int i = 0; i < arr.size(); ++i) {
auto arrTag = ListTag::create();
auto data = arr.get(i).asArray();
NbtListClassAddHelper(arrTag.get(), data);
tag->add(std::move(arrTag));
}
} else if (t.isObject()) {
for (int i = 0; i < arr.size(); ++i) {
auto objTag = CompoundTag::create();
auto data = arr.get(i).asObject();
NbtCompoundClassAddHelper(objTag.get(), data);
tag->add(std::move(objTag));
}
} else {
throw script::Exception("Wrong Type of data to set into NBT List!");
}
}
}
NbtListClass* NbtListClass::constructor(const Arguments& args) {
try {
auto tag = ListTag::create();
if (args.size() >= 1 && args[0].isArray()) {
auto arr = args[0].asArray();
NbtListClassAddHelper(tag.get(), arr);
}
return new NbtListClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create ListTag!");
}
ListTag* NbtListClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtListClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtListClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtListClass::pack(ListTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<ListTag> nbt(tag);
auto* nbtObj = new NbtListClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtListClass(tag->copyList()))->getScriptObject();
}
CATCH("Fail in construct NbtList!");
}
Local<Value> NbtListClass::pack(std::unique_ptr<ListTag> tag) {
try {
return (new NbtListClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtList!");
}
Local<Value> NbtListClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::List);
}
Local<Value> NbtListClass::getSize(const Arguments& args) {
try {
return Number::newNumber((int)nbt->getSize());
}
CATCH("Fail in NBT GetSize!");
}
Local<Value> NbtListClass::getTypeOf(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
return Local<Value>();
}
return Number::newNumber(int(list[index]->getTagType()));
}
CATCH("Fail in NBT GetTypeOf!");
}
Local<Value> NbtListClass::setEnd(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::End) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asEndTag()->set();
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetEnd!");
}
Local<Value> NbtListClass::setByte(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::Byte) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asByteTag()->set(args[1].toInt());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetByte!");
}
Local<Value> NbtListClass::setInt(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::Int) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asIntTag()->set(args[1].toInt());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetInt!");
}
Local<Value> NbtListClass::setShort(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::Short) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asShortTag()->set(args[1].toInt());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetShort!");
}
Local<Value> NbtListClass::setLong(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::Int64) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asInt64Tag()->set(args[1].asNumber().toInt64());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetLong!");
}
Local<Value> NbtListClass::setFloat(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::Float) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asFloatTag()->set(args[1].asNumber().toFloat());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetFloat!");
}
Local<Value> NbtListClass::setDouble(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::Double) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asDoubleTag()->set(args[1].asNumber().toDouble());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetDouble!");
}
Local<Value> NbtListClass::setString(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kString);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::String) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
list[index]->asStringTag()->set(args[1].toStr());
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetString!");
}
Local<Value> NbtListClass::setByteArray(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
CHECK_ARG_TYPE(args[1], ValueKind::kByteBuffer);
try {
auto list = nbt->get();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
} else if (list[0]->getTagType() != Tag::Type::ByteArray) {
LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!");
} else {
auto data = args[1].asByteBuffer();
list[index]->asByteArrayTag()->set(TagMemoryChunk((char*)data.getRawBytes(), data.byteLength()));
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetByteArray!");
}
Local<Value> NbtListClass::setTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto& list = nbt->value();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
return Local<Value>();
}
if (IsInstanceOf<NbtEndClass>(args[1])) {
list[index] = NbtEndClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtByteClass>(args[1])) {
list[index] = NbtByteClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtShortClass>(args[1])) {
list[index] = NbtShortClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtIntClass>(args[1])) {
list[index] = NbtIntClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtLongClass>(args[1])) {
list[index] = NbtLongClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtFloatClass>(args[1])) {
list[index] = NbtFloatClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtDoubleClass>(args[1])) {
list[index] = NbtDoubleClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtStringClass>(args[1])) {
list[index] = NbtStringClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtByteArrayClass>(args[1])) {
list[index] = NbtByteArrayClass::extract(args[1])->copy().release();
} else if (IsInstanceOf<NbtListClass>(args[1])) {
list[index] = NbtListClass::extract(args[1])->copyList().release();
} else if (IsInstanceOf<NbtCompoundClass>(args[1])) {
list[index] = NbtCompoundClass::extract(args[1])->clone().release();
} else {
LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot set Tag into List");
return Local<Value>();
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetTag!");
}
Local<Value> NbtListClass::addTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
try {
if (IsInstanceOf<NbtEndClass>(args[0])) {
nbt->add(NbtEndClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtByteClass>(args[0])) {
nbt->add(NbtByteClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtShortClass>(args[0])) {
nbt->add(NbtShortClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtIntClass>(args[0])) {
nbt->add(NbtIntClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtLongClass>(args[0])) {
nbt->add(NbtLongClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtFloatClass>(args[0])) {
nbt->add(NbtFloatClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtDoubleClass>(args[0])) {
nbt->add(NbtDoubleClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtStringClass>(args[0])) {
nbt->add(NbtStringClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtByteArrayClass>(args[0])) {
nbt->add(NbtByteArrayClass::extract(args[0])->copy());
} else if (IsInstanceOf<NbtListClass>(args[0])) {
nbt->add(NbtListClass::extract(args[0])->copyList());
} else if (IsInstanceOf<NbtCompoundClass>(args[0])) {
nbt->add(NbtCompoundClass::extract(args[0])->clone());
} else {
LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot add Tag into List");
return Local<Value>();
}
return this->getScriptObject();
}
CATCH("Fail in NBT AddTag!");
}
Local<Value> NbtListClass::removeTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto& list = nbt->value();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!");
return Local<Value>();
}
list.erase(list.begin() + index); //===== delete?
return this->getScriptObject();
}
CATCH("Fail in NBT SetTag!");
}
Local<Value> NbtListClass::getData(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto& list = nbt->value();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
return Local<Value>();
}
return Tag2Value(list[index]);
}
CATCH("Fail in NBTgetData!")
}
Local<Value> NbtListClass::getTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto& list = nbt->value();
auto index = args[0].toInt();
if (index >= list.size() || index < 0) {
return Local<Value>();
}
Local<Value> res;
switch (list[index]->getTagType()) {
case Tag::Type::End:
res = NbtEndClass::pack(list[index]->asEndTag(), true); // share ptr
break;
case Tag::Type::Byte:
res = NbtByteClass::pack(list[index]->asByteTag(), true); // share ptr
break;
case Tag::Type::Short:
res = NbtShortClass::pack(list[index]->asShortTag(), true); // share ptr
break;
case Tag::Type::Int:
res = NbtIntClass::pack(list[index]->asIntTag(), true); // share ptr
break;
case Tag::Type::Int64:
res = NbtLongClass::pack(list[index]->asInt64Tag(), true); // share ptr
break;
case Tag::Type::Float:
res = NbtFloatClass::pack(list[index]->asFloatTag(), true); // share ptr
break;
case Tag::Type::Double:
res = NbtDoubleClass::pack(list[index]->asDoubleTag(), true); // share ptr
break;
case Tag::Type::String:
res = NbtStringClass::pack(list[index]->asStringTag(), true); // share ptr
break;
case Tag::Type::ByteArray:
res = NbtByteArrayClass::pack(list[index]->asByteArrayTag(), true); // share ptr
break;
case Tag::Type::List:
res = NbtListClass::pack(list[index]->asListTag(), true); // share ptr
break;
case Tag::Type::Compound:
res = NbtCompoundClass::pack(list[index]->asCompoundTag(), true); // share ptr
break;
default:
res = Local<Value>();
break;
}
return res;
}
CATCH("Fail in NBT GetTag!");
}
Local<Value> NbtListClass::toArray(const Arguments& args) {
try {
auto& list = nbt->value();
Local<Array> arr = Array::newArray();
for (auto& tag : list) {
arr.add(Tag2Value(tag, true));
}
return arr;
}
CATCH("Fail in NBTtoArray!");
}
Local<Value> NbtListClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
//////////////////// Classes NbtCompound ////////////////////
NbtCompoundClass::NbtCompoundClass(const Local<Object>& scriptObj, std::unique_ptr<CompoundTag> p)
: ScriptClass(scriptObj) {
nbt = std::move(p);
}
NbtCompoundClass::NbtCompoundClass(std::unique_ptr<CompoundTag> p)
: ScriptClass(ScriptClass::ConstructFromCpp<NbtCompoundClass>{}) {
nbt = std::move(p);
}
////////////////// Helper //////////////////
void NbtCompoundClassAddHelper(CompoundTag* tag, Local<Object>& obj) {
auto keys = obj.getKeyNames();
if (keys.size() > 0) {
for (int i = 0; i < keys.size(); ++i) {
Local<Value> t = obj.get(keys[i]);
if (IsInstanceOf<NbtEndClass>(t))
tag->put(keys[i], NbtEndClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtByteClass>(t))
tag->put(keys[i], NbtByteClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtShortClass>(t))
tag->put(keys[i], NbtShortClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtIntClass>(t))
tag->put(keys[i], NbtIntClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtLongClass>(t))
tag->put(keys[i], NbtLongClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtFloatClass>(t))
tag->put(keys[i], NbtFloatClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtDoubleClass>(t))
tag->put(keys[i], NbtDoubleClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtStringClass>(t))
tag->put(keys[i], NbtStringClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtByteArrayClass>(t))
tag->put(keys[i], NbtByteArrayClass::extract(obj.get(keys[i]))->copy());
else if (IsInstanceOf<NbtListClass>(t))
tag->put(keys[i], NbtListClass::extract(obj.get(keys[i]))->copyList());
else if (IsInstanceOf<NbtCompoundClass>(t))
tag->put(keys[i], NbtCompoundClass::extract(obj.get(keys[i]))->clone());
else if (t.isArray()) {
auto arrTag = ListTag::create();
auto data = obj.get(keys[i]).asArray();
NbtListClassAddHelper(arrTag.get(), data);
tag->put(keys[i], std::move(arrTag));
} else if (t.isObject()) {
auto objTag = CompoundTag::create();
auto data = obj.get(keys[i]).asObject();
NbtCompoundClassAddHelper(objTag.get(), data);
tag->put(keys[i], std::move(objTag));
} else {
LOG_ERROR_WITH_SCRIPT_INFO("Wrong Type of data to set into NBT Compound!");
}
}
}
}
NbtCompoundClass* NbtCompoundClass::constructor(const Arguments& args) {
try {
auto tag = CompoundTag::create();
if (args.size() >= 1 && args[0].isObject()) {
auto obj = args[0].asObject();
NbtCompoundClassAddHelper(tag.get(), obj);
}
return new NbtCompoundClass(args.thiz(), std::move(tag));
}
CATCH_C("Fail in Create ListTag!");
}
CompoundTag* NbtCompoundClass::extract(Local<Value> v) {
if (EngineScope::currentEngine()->isInstanceOf<NbtCompoundClass>(v))
return EngineScope::currentEngine()->getNativeInstance<NbtCompoundClass>(v)->nbt.get();
else
return nullptr;
}
Local<Value> NbtCompoundClass::pack(CompoundTag* tag, bool noDelete) {
try {
if (noDelete) // unique_ptr 共享指针 + noDelete
{
std::unique_ptr<CompoundTag> nbt(tag);
auto* nbtObj = new NbtCompoundClass(std::move(nbt));
nbtObj->canDelete = false;
return nbtObj->getScriptObject();
} else
return (new NbtCompoundClass(tag->clone()))->getScriptObject();
}
CATCH("Fail in construct NbtCompound!");
}
Local<Value> NbtCompoundClass::pack(std::unique_ptr<CompoundTag> tag) {
try {
return (new NbtCompoundClass(std::move(tag)))->getScriptObject();
}
CATCH("Fail in construct NbtCompound!");
}
Local<Value> NbtCompoundClass::getType(const Arguments& args) {
return Number::newNumber((int)Tag::Type::Compound);
}
Local<Value> NbtCompoundClass::getKeys(const Arguments& args) {
try {
Local<Array> arr = Array::newArray();
auto& list = nbt->value();
for (auto& [k, v] : list) {
arr.add(String::newString(k));
}
return arr;
}
CATCH("Fail in NBT GetKeys!");
}
Local<Value> NbtCompoundClass::getTypeOf(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto& list = nbt->value();
auto key = args[0].toStr();
return Number::newNumber(int(list.at(key).getTagType()));
} catch (const out_of_range& e) {
return Local<Value>();
}
CATCH("Fail in NBT GetTypeOf!");
}
Local<Value> NbtCompoundClass::setEnd(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto key = args[0].toStr();
nbt->putByte(key, (char)0);
return this->getScriptObject();
}
CATCH("Fail in NBT SetEnd!");
}
Local<Value> NbtCompoundClass::setByte(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto key = args[0].toStr();
auto data = char(args[1].toInt());
nbt->putByte(key, data);
return this->getScriptObject();
}
CATCH("Fail in NBT SetByte!");
}
Local<Value> NbtCompoundClass::setInt(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto key = args[0].toStr();
auto data = int(args[1].toInt());
nbt->putInt(key, data);
return this->getScriptObject();
}
CATCH("Fail in NBT SetInt!");
}
Local<Value> NbtCompoundClass::setShort(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto key = args[0].toStr();
auto data = short(args[1].toInt());
nbt->putShort(key, data);
return this->getScriptObject();
}
CATCH("Fail in NBT SetShort!");
}
Local<Value> NbtCompoundClass::setLong(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto key = args[0].toStr();
auto data = args[1].asNumber().toInt64();
nbt->putInt64(key, data);
return this->getScriptObject();
}
CATCH("Fail in NBT SetLong!");
}
Local<Value> NbtCompoundClass::setFloat(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto key = args[0].toStr();
auto data = args[1].asNumber().toFloat();
nbt->putFloat(key, data);
return this->getScriptObject();
}
CATCH("Fail in NBT SetFloat!");
}
Local<Value> NbtCompoundClass::setDouble(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kNumber);
try {
auto& list = nbt->value();
auto key = args[0].toStr();
auto data = args[1].asNumber().toDouble();
list.at(key).asDoubleTag()->value() = data;
return this->getScriptObject();
}
CATCH("Fail in NBT SetDouble!");
}
Local<Value> NbtCompoundClass::setString(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kString);
try {
auto key = args[0].toStr();
auto data = args[1].toStr();
nbt->putString(key, data);
return this->getScriptObject();
}
CATCH("Fail in NBT SetString!");
}
Local<Value> NbtCompoundClass::setByteArray(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
CHECK_ARG_TYPE(args[1], ValueKind::kByteBuffer);
try {
auto key = args[0].toStr();
auto data = args[1].asByteBuffer();
nbt->putByteArray(key, (char*)data.getRawBytes(), data.byteLength());
return this->getScriptObject();
}
CATCH("Fail in NBT SetString!");
}
Local<Value> NbtCompoundClass::setTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 2);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto key = args[0].toStr();
if (IsInstanceOf<NbtEndClass>(args[1])) {
nbt->put(key, std::move(NbtEndClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtByteClass>(args[1])) {
nbt->put(key, std::move(NbtByteClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtShortClass>(args[1])) {
nbt->put(key, std::move(NbtShortClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtIntClass>(args[1])) {
nbt->put(key, std::move(NbtIntClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtLongClass>(args[1])) {
nbt->put(key, std::move(NbtLongClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtFloatClass>(args[1])) {
nbt->put(key, std::move(NbtFloatClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtDoubleClass>(args[1])) {
nbt->put(key, std::move(NbtDoubleClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtStringClass>(args[1])) {
nbt->put(key, std::move(NbtStringClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtByteArrayClass>(args[1])) {
nbt->put(key, std::move(NbtByteArrayClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtListClass>(args[1])) {
nbt->put(key, std::move(NbtListClass::extract(args[1])->copy()));
} else if (IsInstanceOf<NbtCompoundClass>(args[1])) {
nbt->put(key, std::move(NbtCompoundClass::extract(args[1])->copy()));
} else {
LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot set Tag into Compound");
return Local<Value>();
}
return this->getScriptObject();
}
CATCH("Fail in NBT SetTag!");
}
Local<Value> NbtCompoundClass::removeTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto& list = nbt->value();
auto key = args[0].toStr();
list.erase(key);
return this->getScriptObject();
} catch (const out_of_range& e) {
LOG_ERROR_WITH_SCRIPT_INFO("Key no found in NBT Compound!");
return Local<Value>();
}
CATCH("Fail in NBT RemoveTag!");
}
Local<Value> NbtCompoundClass::getData(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto& list = nbt->value();
auto key = args[0].toStr();
return Tag2Value(list.at(key).asTag());
} catch (const out_of_range& e) {
return Local<Value>();
}
CATCH("Fail in NBT GetData!")
}
Local<Value> NbtCompoundClass::getTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto key = args[0].toStr();
Local<Value> res;
switch (nbt->value().at(key).getTagType()) {
case Tag::Type::End:
res = NbtEndClass::pack(nbt->value().at(key).asEndTag(), true); // share ptr
break;
case Tag::Type::Byte:
res = NbtByteClass::pack((ByteTag*)nbt->getByteTag(key), true); // share ptr
break;
case Tag::Type::Short:
res = NbtShortClass::pack((ShortTag*)nbt->getShortTag(key), true); // share ptr
break;
case Tag::Type::Int:
res = NbtIntClass::pack((IntTag*)nbt->getIntTag(key), true); // share ptr
break;
case Tag::Type::Int64:
res = NbtLongClass::pack((Int64Tag*)nbt->getInt64Tag(key), true); // share ptr
break;
case Tag::Type::Float:
res = NbtFloatClass::pack((FloatTag*)nbt->getFloatTag(key), true); // share ptr
break;
case Tag::Type::Double:
res = NbtDoubleClass::pack((DoubleTag*)nbt->getDoubleTag(key), true); // share ptr
break;
case Tag::Type::String:
res = NbtStringClass::pack((StringTag*)nbt->getStringTag(key), true); // share ptr
break;
case Tag::Type::ByteArray:
res = NbtByteArrayClass::pack((ByteArrayTag*)nbt->getByteArrayTag(key), true); // share ptr
break;
case Tag::Type::List:
res = NbtListClass::pack((ListTag*)nbt->getListTag(key), true); // share ptr
break;
case Tag::Type::Compound:
res = NbtCompoundClass::pack((CompoundTag*)nbt->getCompoundTag(key), true); // share ptr
break;
default:
res = Local<Value>();
break;
}
return res;
} catch (const out_of_range& e) {
return Local<Value>();
}
CATCH("Fail in NBT GetTag!");
}
Local<Value> NbtCompoundClass::toObject(const Arguments& args) {
try {
auto& comp = nbt->value();
Local<Object> obj = Object::newObject();
for (auto& [k, v] : comp) {
obj.set(k, Tag2Value(v.asTag(), true));
}
return obj;
}
CATCH("Fail in NBT ToObject!");
}
Local<Value> NbtCompoundClass::toSNBT(const Arguments& args) {
try {
int indent = args.size() >= 1 ? args[0].toInt() : -1;
if (indent == -1)
return String::newString(nbt->toSNBT(0, SnbtFormat::Minimize));
else
return String::newString(nbt->toSNBT(indent, SnbtFormat::PartialNewLine));
}
CATCH("Fail in toSNBT!");
}
Local<Value> NbtCompoundClass::toBinaryNBT(const Arguments& args) {
try {
auto res = nbt->toBinaryNBT();
return ByteBuffer::newByteBuffer(res.data(), res.size());
}
CATCH("Fail in toBinaryNBT!");
}
Local<Value> NbtCompoundClass::toString(const Arguments& args) {
if (args.size() >= 1)
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
return String::newString(nbt->toJson(args.size() >= 1 ? args[0].toInt() : -1));
}
CATCH("Fail in NBTtoJson!");
}
Local<Value> NbtCompoundClass::destroy(const Arguments& args) {
return Boolean::newBoolean(true);
}
//////////////////// APIs ////////////////////
Local<Value> NbtStatic::newTag(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
try {
auto type = args[0].toInt();
Local<Value> res;
switch (type) {
case Tag::Type::End: {
auto tag = EndTag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set();
}
res = NbtEndClass::pack(std::move(tag));
break;
}
case Tag::Type::Byte: {
auto tag = ByteTag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set(args[1].toInt());
}
res = NbtByteClass::pack(std::move(tag));
break;
}
case Tag::Type::Short: {
auto tag = ShortTag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set(args[1].toInt());
}
res = NbtShortClass::pack(std::move(tag));
break;
}
case Tag::Type::Int: {
auto tag = IntTag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set(args[1].toInt());
}
res = NbtIntClass::pack(std::move(tag));
break;
}
case Tag::Type::Int64: {
auto tag = Int64Tag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set(args[1].asNumber().toInt64());
}
res = NbtLongClass::pack(std::move(tag));
break;
}
case Tag::Type::Float: {
auto tag = FloatTag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set(args[1].asNumber().toFloat());
}
res = NbtFloatClass::pack(std::move(tag));
break;
}
case Tag::Type::Double: {
auto tag = DoubleTag::create();
if (args.size() >= 2 && args[1].isNumber()) {
tag->set(args[1].asNumber().toDouble());
}
res = NbtDoubleClass::pack(std::move(tag));
break;
}
case Tag::Type::String: {
auto tag = StringTag::create();
if (args.size() >= 2 && args[1].isString()) {
tag->set(args[1].toStr());
}
res = NbtStringClass::pack(std::move(tag));
break;
}
case Tag::Type::ByteArray: {
auto tag = ByteArrayTag::create();
if (args.size() >= 2 && args[1].isByteBuffer()) {
Local<ByteBuffer> buf = args[1].asByteBuffer();
tag->set(TagMemoryChunk((char*)buf.getRawBytes(), buf.byteLength()));
}
res = NbtByteArrayClass::pack(std::move(tag));
break;
}
case Tag::Type::List: {
auto tag = ListTag::create();
if (args.size() >= 2 && args[1].isArray()) {
Local<Array> arr = args[1].asArray();
NbtListClassAddHelper(tag.get(), arr);
}
res = NbtListClass::pack(std::move(tag));
break;
}
case Tag::Type::Compound: {
auto tag = CompoundTag::create();
if (args.size() >= 2 && args[1].isObject()) {
Local<Object> obj = args[1].asObject();
NbtCompoundClassAddHelper(tag.get(), obj);
}
res = NbtCompoundClass::pack(std::move(tag));
break;
}
default:
res = Local<Value>();
break;
}
return res;
}
CATCH("Fail in NBT CreateTag!");
}
Local<Value> NbtStatic::parseSNBT(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kString);
try {
auto tag = CompoundTag::fromSNBT(args[0].toStr());
if (tag)
return NbtCompoundClass::pack(std::move(tag));
else
return Local<Value>();
}
CATCH("Fail in parseSNBT!");
}
Local<Value> NbtStatic::parseBinaryNBT(const Arguments& args) {
CHECK_ARGS_COUNT(args, 1);
CHECK_ARG_TYPE(args[0], ValueKind::kByteBuffer);
try {
auto data = args[0].asByteBuffer();
auto tag = CompoundTag::fromBinaryNBT(data.getRawBytes(), data.byteLength());
if (tag)
return NbtCompoundClass::pack(std::move(tag));
else
return Local<Value>();
}
CATCH("Fail in parseBinaryNBT!");
}
//////////////////// Helper ////////////////////
bool IsNbtClass(Local<Value> value) {
return IsInstanceOf<NbtEndClass>(value) || IsInstanceOf<NbtByteClass>(value) || IsInstanceOf<NbtShortClass>(value) || IsInstanceOf<NbtIntClass>(value) || IsInstanceOf<NbtLongClass>(value) || IsInstanceOf<NbtFloatClass>(value) || IsInstanceOf<NbtDoubleClass>(value) || IsInstanceOf<NbtStringClass>(value) || IsInstanceOf<NbtByteArrayClass>(value) || IsInstanceOf<NbtListClass>(value) || IsInstanceOf<NbtCompoundClass>(value);
}
//////////////////// Tag To Value ////////////////////
Local<Value> Tag2Value_CompoundHelper(CompoundTag* nbt, bool autoExpansion = false);
Local<Value> Tag2Value_ListHelper(ListTag* nbt, bool autoExpansion = false) {
Local<Array> res = Array::newArray();
auto& list = nbt->asListTag()->value();
for (auto& tag : list) {
switch (tag->getTagType()) {
case Tag::Type::End:
res.add(Local<Value>());
break;
case Tag::Type::Byte:
res.add(Number::newNumber(tag->asByteTag()->value()));
break;
case Tag::Type::Short:
res.add(Number::newNumber(tag->asShortTag()->value()));
break;
case Tag::Type::Int:
res.add(Number::newNumber(tag->asIntTag()->value()));
break;
case Tag::Type::Int64:
res.add(Number::newNumber(tag->asInt64Tag()->value()));
break;
case Tag::Type::Float:
res.add(Number::newNumber(tag->asFloatTag()->value()));
break;
case Tag::Type::Double:
res.add(Number::newNumber(tag->asDoubleTag()->value()));
break;
case Tag::Type::String:
res.add(String::newString(tag->asStringTag()->value()));
break;
case Tag::Type::ByteArray: {
auto& data = tag->asByteArrayTag()->value();
res.add(ByteBuffer::newByteBuffer(data.data.get(), data.size));
break;
}
case Tag::Type::List:
if (!autoExpansion)
res.add(NbtListClass::pack(tag->asListTag()));
else
res.add(Tag2Value_ListHelper(tag->asListTag(), autoExpansion));
break;
case Tag::Type::Compound:
if (!autoExpansion)
res.add(NbtCompoundClass::pack(tag->asCompoundTag()));
else
res.add(Tag2Value_CompoundHelper(tag->asCompoundTag(), autoExpansion));
default:
res.add(Local<Value>());
break;
}
}
return res;
}
Local<Value> Tag2Value_CompoundHelper(CompoundTag* nbt, bool autoExpansion) {
Local<Object> res = Object::newObject();
auto& list = nbt->asCompoundTag()->value();
for (auto& [key, tag] : list) {
switch (tag.getTagType()) {
case Tag::Type::End:
res.set(key, Local<Value>());
break;
case Tag::Type::Byte:
res.set(key, Number::newNumber(tag.asByteTag()->get()));
break;
case Tag::Type::Short:
res.set(key, Number::newNumber(tag.asShortTag()->get()));
break;
case Tag::Type::Int:
res.set(key, Number::newNumber(tag.asIntTag()->get()));
break;
case Tag::Type::Int64:
res.set(key, Number::newNumber(tag.asInt64Tag()->get()));
break;
case Tag::Type::Float:
res.set(key, Number::newNumber(tag.asFloatTag()->get()));
break;
case Tag::Type::Double:
res.set(key, Number::newNumber(tag.asDoubleTag()->get()));
break;
case Tag::Type::String:
res.set(key, String::newString(tag.asStringTag()->get()));
break;
case Tag::Type::ByteArray: {
auto& data = tag.asByteArrayTag()->value();
res.set(key, ByteBuffer::newByteBuffer(data.data.get(), data.size));
break;
}
case Tag::Type::List:
if (!autoExpansion)
res.set(key, NbtListClass::pack(tag.asListTag()));
else
res.set(key, Tag2Value_ListHelper(tag.asListTag(), autoExpansion));
break;
case Tag::Type::Compound:
if (!autoExpansion)
res.set(key, NbtCompoundClass::pack(tag.asCompoundTag()));
else
res.set(key, Tag2Value_CompoundHelper(tag.asCompoundTag(), autoExpansion));
default:
res.set(key, Local<Value>());
break;
}
}
return res;
}
Local<Value> Tag2Value(Tag* nbt, bool autoExpansion) {
Local<Value> value;
switch (nbt->getTagType()) {
case Tag::Type::End:
value = Number::newNumber(0);
break;
case Tag::Type::Byte:
value = Number::newNumber(nbt->asByteTag()->get());
break;
case Tag::Type::Short:
value = Number::newNumber(nbt->asShortTag()->get());
break;
case Tag::Type::Int:
value = Number::newNumber(nbt->asIntTag()->get());
break;
case Tag::Type::Int64:
value = Number::newNumber(nbt->asInt64Tag()->get());
break;
case Tag::Type::Float:
value = Number::newNumber(nbt->asFloatTag()->get());
break;
case Tag::Type::Double:
value = Number::newNumber(nbt->asDoubleTag()->get());
break;
case Tag::Type::String:
value = String::newString(nbt->asStringTag()->get());
break;
case Tag::Type::ByteArray: {
auto& data = nbt->asByteArrayTag()->value();
value = ByteBuffer::newByteBuffer(data.data.get(), data.size);
break;
}
case Tag::Type::List:
if (!autoExpansion)
value = NbtListClass::pack(nbt->asListTag());
else
value = Tag2Value_ListHelper(nbt->asListTag(), autoExpansion);
break;
case Tag::Type::Compound:
if (!autoExpansion)
value = NbtCompoundClass::pack(nbt->asCompoundTag());
else
value = Tag2Value_CompoundHelper(nbt->asCompoundTag(), autoExpansion);
break;
default:
value = Local<Value>();
break;
}
return value;
}