#include "APIHelp.h" #include "NbtAPI.h" #include #include #include "ItemAPI.h" #include "BlockAPI.h" #include #include #include #include #include #include #include #include #include #include #include using namespace std; //////////////////// Class Definition //////////////////// ClassDefine NbtStaticBuilder = defineClass("NBT") .function("parseSNBT", &NbtStatic::parseSNBT) .function("parseBinaryNBT", &NbtStatic::parseBinaryNBT) .property("End", &NbtStatic::getType) .property("Byte", &NbtStatic::getType) .property("Short", &NbtStatic::getType) .property("Int", &NbtStatic::getType) .property("Long", &NbtStatic::getType) .property("Float", &NbtStatic::getType) .property("Double", &NbtStatic::getType) .property("ByteArray", &NbtStatic::getType) .property("String", &NbtStatic::getType) .property("List", &NbtStatic::getType) .property("Compound", &NbtStatic::getType) // For Compatibility .function("createTag", &NbtStatic::newTag) .function("newTag", &NbtStatic::newTag) .build(); ClassDefine NbtEndClassBuilder = defineClass("NbtEnd") .constructor(&NbtEndClass::constructor) .instanceFunction("getType", &NbtEndClass::getType) .instanceFunction("toString", &NbtEndClass::toString) .instanceFunction("set", &NbtEndClass::set) .instanceFunction("get", &NbtEndClass::get) .build(); ClassDefine NbtByteClassBuilder = defineClass("NbtByte") .constructor(&NbtByteClass::constructor) .instanceFunction("getType", &NbtByteClass::getType) .instanceFunction("toString", &NbtByteClass::toString) .instanceFunction("set", &NbtByteClass::set) .instanceFunction("get", &NbtByteClass::get) .build(); ClassDefine NbtShortClassBuilder = defineClass("NbtShort") .constructor(&NbtShortClass::constructor) .instanceFunction("getType", &NbtShortClass::getType) .instanceFunction("toString", &NbtShortClass::toString) .instanceFunction("set", &NbtShortClass::set) .instanceFunction("get", &NbtShortClass::get) .build(); ClassDefine NbtIntClassBuilder = defineClass("NbtInt") .constructor(&NbtIntClass::constructor) .instanceFunction("getType", &NbtIntClass::getType) .instanceFunction("toString", &NbtIntClass::toString) .instanceFunction("set", &NbtIntClass::set) .instanceFunction("get", &NbtIntClass::get) .build(); ClassDefine NbtLongClassBuilder = defineClass("NbtLong") .constructor(&NbtLongClass::constructor) .instanceFunction("getType", &NbtLongClass::getType) .instanceFunction("toString", &NbtLongClass::toString) .instanceFunction("set", &NbtLongClass::set) .instanceFunction("get", &NbtLongClass::get) .build(); ClassDefine NbtFloatClassBuilder = defineClass("NbtFloat") .constructor(&NbtFloatClass::constructor) .instanceFunction("getType", &NbtFloatClass::getType) .instanceFunction("toString", &NbtFloatClass::toString) .instanceFunction("set", &NbtFloatClass::set) .instanceFunction("get", &NbtFloatClass::get) .build(); ClassDefine NbtDoubleClassBuilder = defineClass("NbtDouble") .constructor(&NbtDoubleClass::constructor) .instanceFunction("getType", &NbtDoubleClass::getType) .instanceFunction("toString", &NbtDoubleClass::toString) .instanceFunction("set", &NbtDoubleClass::set) .instanceFunction("get", &NbtDoubleClass::get) .build(); ClassDefine NbtStringClassBuilder = defineClass("NbtString") .constructor(&NbtStringClass::constructor) .instanceFunction("getType", &NbtStringClass::getType) .instanceFunction("toString", &NbtStringClass::toString) .instanceFunction("set", &NbtStringClass::set) .instanceFunction("get", &NbtStringClass::get) .build(); ClassDefine NbtByteArrayClassBuilder = defineClass("NbtByteArray") .constructor(&NbtByteArrayClass::constructor) .instanceFunction("getType", &NbtByteArrayClass::getType) .instanceFunction("toString", &NbtByteArrayClass::toString) .instanceFunction("set", &NbtByteArrayClass::set) .instanceFunction("get", &NbtByteArrayClass::get) .build(); ClassDefine NbtListClassBuilder = defineClass("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 NbtCompoundClassBuilder = defineClass("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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtEndClass::NbtEndClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtEndClass::pack(EndTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtEndClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtEndClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtEnd!"); } Local NbtEndClass::pack(std::unique_ptr tag) { try { return (new NbtEndClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtEnd!"); } Local NbtEndClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::End); } Local NbtEndClass::get(const Arguments& args) { try { return Local(); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtByteClass::NbtByteClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtByteClass::pack(ByteTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtByteClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtByteClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtByte!"); } Local NbtByteClass::pack(std::unique_ptr tag) { try { return (new NbtByteClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtByte!"); } Local NbtByteClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Byte); } Local NbtByteClass::get(const Arguments& args) { try { return Number::newNumber(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtIntClass::NbtIntClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtIntClass::pack(IntTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtIntClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtIntClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtInt!"); } Local NbtIntClass::pack(std::unique_ptr tag) { try { return (new NbtIntClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtInt!"); } Local NbtIntClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Int); } Local NbtIntClass::get(const Arguments& args) { try { return Number::newNumber(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtShortClass::NbtShortClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtShortClass::pack(ShortTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtShortClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtShortClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtShort!"); } Local NbtShortClass::pack(std::unique_ptr tag) { try { return (new NbtShortClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtShort!"); } Local NbtShortClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Short); } Local NbtShortClass::get(const Arguments& args) { try { return Number::newNumber(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtLongClass::NbtLongClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtLongClass::pack(Int64Tag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtLongClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtLongClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtLong!"); } Local NbtLongClass::pack(std::unique_ptr tag) { try { return (new NbtLongClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtLong!"); } Local NbtLongClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Int64); } Local NbtLongClass::get(const Arguments& args) { try { return Number::newNumber(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtFloatClass::NbtFloatClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtFloatClass::pack(FloatTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtFloatClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtFloatClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtFloat!"); } Local NbtFloatClass::pack(std::unique_ptr tag) { try { return (new NbtFloatClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtFloat!"); } Local NbtFloatClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Float); } Local NbtFloatClass::get(const Arguments& args) { try { return Number::newNumber(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtDoubleClass::NbtDoubleClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtDoubleClass::pack(DoubleTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtDoubleClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtDoubleClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtDouble!"); } Local NbtDoubleClass::pack(std::unique_ptr tag) { try { return (new NbtDoubleClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtDouble!"); } Local NbtDoubleClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Double); } Local NbtDoubleClass::get(const Arguments& args) { try { return Number::newNumber(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtStringClass::NbtStringClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtStringClass::pack(StringTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtStringClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtStringClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtString!"); } Local NbtStringClass::pack(std::unique_ptr tag) { try { return (new NbtStringClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtString!"); } Local NbtStringClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::String); } Local NbtStringClass::get(const Arguments& args) { try { return String::newString(nbt->get()); } CATCH("Fail in NbtValueGet!") } Local 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 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtByteArrayClass::NbtByteArrayClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { 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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtByteArrayClass::pack(ByteArrayTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr nbt(tag); auto* nbtObj = new NbtByteArrayClass(std::move(nbt)); nbtObj->canDelete = false; return nbtObj->getScriptObject(); } else return (new NbtByteArrayClass(Tag::asTypedTag(tag->copy())))->getScriptObject(); } CATCH("Fail in construct NbtByteArray!"); } Local NbtByteArrayClass::pack(std::unique_ptr tag) { try { return (new NbtByteArrayClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtByteArray!"); } Local NbtByteArrayClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::ByteArray); } Local NbtByteArrayClass::get(const Arguments& args) { try { auto& data = nbt->value(); return ByteBuffer::newByteBuffer(data.data.get(), data.size); } CATCH("Fail in NbtValueGet!") } Local 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 NbtByteArrayClass::set(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { Local 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { this->nbt = std::move(p); } NbtListClass::NbtListClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { this->nbt = std::move(p); } ////////////////// Helper ////////////////// void NbtListClassAddHelper(ListTag* tag, Local& arr) { if (arr.size() > 0) { Local t = arr.get(0); if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtEndClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtByteClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtShortClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtIntClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtLongClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtFloatClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtDoubleClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtStringClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtByteArrayClass::extract(arr.get(i))->copy()); else if (IsInstanceOf(t)) for (int i = 0; i < arr.size(); ++i) tag->add(NbtListClass::extract(arr.get(i))->copyList()); else if (IsInstanceOf(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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtListClass::pack(ListTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr 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 NbtListClass::pack(std::unique_ptr tag) { try { return (new NbtListClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtList!"); } Local NbtListClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::List); } Local NbtListClass::getSize(const Arguments& args) { try { return Number::newNumber((int)nbt->getSize()); } CATCH("Fail in NBT GetSize!"); } Local 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(); } return Number::newNumber(int(list[index]->getTagType())); } CATCH("Fail in NBT GetTypeOf!"); } Local 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 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 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 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 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 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 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 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 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 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(); } if (IsInstanceOf(args[1])) { list[index] = NbtEndClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtByteClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtShortClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtIntClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtLongClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtFloatClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtDoubleClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtStringClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtByteArrayClass::extract(args[1])->copy().release(); } else if (IsInstanceOf(args[1])) { list[index] = NbtListClass::extract(args[1])->copyList().release(); } else if (IsInstanceOf(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(); } return this->getScriptObject(); } CATCH("Fail in NBT SetTag!"); } Local NbtListClass::addTag(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { if (IsInstanceOf(args[0])) { nbt->add(NbtEndClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtByteClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtShortClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtIntClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtLongClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtFloatClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtDoubleClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtStringClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtByteArrayClass::extract(args[0])->copy()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtListClass::extract(args[0])->copyList()); } else if (IsInstanceOf(args[0])) { nbt->add(NbtCompoundClass::extract(args[0])->clone()); } else { LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot add Tag into List"); return Local(); } return this->getScriptObject(); } CATCH("Fail in NBT AddTag!"); } Local 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(); } list.erase(list.begin() + index); //===== delete? return this->getScriptObject(); } CATCH("Fail in NBT SetTag!"); } Local 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(); } return Tag2Value(list[index]); } CATCH("Fail in NBTgetData!") } Local 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(); } Local 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(); break; } return res; } CATCH("Fail in NBT GetTag!"); } Local NbtListClass::toArray(const Arguments& args) { try { auto& list = nbt->value(); Local arr = Array::newArray(); for (auto& tag : list) { arr.add(Tag2Value(tag, true)); } return arr; } CATCH("Fail in NBTtoArray!"); } Local 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& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { nbt = std::move(p); } NbtCompoundClass::NbtCompoundClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { nbt = std::move(p); } ////////////////// Helper ////////////////// void NbtCompoundClassAddHelper(CompoundTag* tag, Local& obj) { auto keys = obj.getKeyNames(); if (keys.size() > 0) { for (int i = 0; i < keys.size(); ++i) { Local t = obj.get(keys[i]); if (IsInstanceOf(t)) tag->put(keys[i], NbtEndClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtByteClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtShortClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtIntClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtLongClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtFloatClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtDoubleClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtStringClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtByteArrayClass::extract(obj.get(keys[i]))->copy()); else if (IsInstanceOf(t)) tag->put(keys[i], NbtListClass::extract(obj.get(keys[i]))->copyList()); else if (IsInstanceOf(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 v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); else return nullptr; } Local NbtCompoundClass::pack(CompoundTag* tag, bool noDelete) { try { if (noDelete) // unique_ptr 共享指针 + noDelete { std::unique_ptr 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 NbtCompoundClass::pack(std::unique_ptr tag) { try { return (new NbtCompoundClass(std::move(tag)))->getScriptObject(); } CATCH("Fail in construct NbtCompound!"); } Local NbtCompoundClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Compound); } Local NbtCompoundClass::getKeys(const Arguments& args) { try { Local 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 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(); } CATCH("Fail in NBT GetTypeOf!"); } Local 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 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 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 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 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 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 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 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 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 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(args[1])) { nbt->put(key, std::move(NbtEndClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtByteClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtShortClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtIntClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtLongClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtFloatClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtDoubleClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtStringClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtByteArrayClass::extract(args[1])->copy())); } else if (IsInstanceOf(args[1])) { nbt->put(key, std::move(NbtListClass::extract(args[1])->copy())); } else if (IsInstanceOf(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(); } return this->getScriptObject(); } CATCH("Fail in NBT SetTag!"); } Local 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(); } CATCH("Fail in NBT RemoveTag!"); } Local 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(); } CATCH("Fail in NBT GetData!") } Local NbtCompoundClass::getTag(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kString); try { auto key = args[0].toStr(); Local 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(); break; } return res; } catch (const out_of_range& e) { return Local(); } CATCH("Fail in NBT GetTag!"); } Local NbtCompoundClass::toObject(const Arguments& args) { try { auto& comp = nbt->value(); Local obj = Object::newObject(); for (auto& [k, v] : comp) { obj.set(k, Tag2Value(v.asTag(), true)); } return obj; } CATCH("Fail in NBT ToObject!"); } Local 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 NbtCompoundClass::toBinaryNBT(const Arguments& args) { try { auto res = nbt->toBinaryNBT(); return ByteBuffer::newByteBuffer(res.data(), res.size()); } CATCH("Fail in toBinaryNBT!"); } Local 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 NbtCompoundClass::destroy(const Arguments& args) { return Boolean::newBoolean(true); } //////////////////// APIs //////////////////// Local NbtStatic::newTag(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); try { auto type = args[0].toInt(); Local 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 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 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 obj = args[1].asObject(); NbtCompoundClassAddHelper(tag.get(), obj); } res = NbtCompoundClass::pack(std::move(tag)); break; } default: res = Local(); break; } return res; } CATCH("Fail in NBT CreateTag!"); } Local 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(); } CATCH("Fail in parseSNBT!"); } Local 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(); } CATCH("Fail in parseBinaryNBT!"); } //////////////////// Helper //////////////////// bool IsNbtClass(Local value) { return IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value); } //////////////////// Tag To Value //////////////////// Local Tag2Value_CompoundHelper(CompoundTag* nbt, bool autoExpansion = false); Local Tag2Value_ListHelper(ListTag* nbt, bool autoExpansion = false) { Local res = Array::newArray(); auto& list = nbt->asListTag()->value(); for (auto& tag : list) { switch (tag->getTagType()) { case Tag::Type::End: res.add(Local()); 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()); break; } } return res; } Local Tag2Value_CompoundHelper(CompoundTag* nbt, bool autoExpansion) { Local res = Object::newObject(); auto& list = nbt->asCompoundTag()->value(); for (auto& [key, tag] : list) { switch (tag.getTagType()) { case Tag::Type::End: res.set(key, Local()); 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()); break; } } return res; } Local Tag2Value(Tag* nbt, bool autoExpansion) { Local 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(); break; } return value; }