#include "APIHelp.h" #include "BaseAPI.h" #include "BlockAPI.h" #include "DeviceAPI.h" #include "PlayerAPI.h" #include "McAPI.h" #include "ContainerAPI.h" #include "ItemAPI.h" #include "EntityAPI.h" #include "NbtAPI.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; Local McClass::spawnSimulatedPlayer(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kString); try { std::string name = args[0].toStr(); if (args.size() == 1) { if (auto sp = SimulatedPlayer::create(name)) return PlayerClass::newPlayer(sp); else return Local(); } auto dimid = 0; BlockPos bpos; if (IsInstanceOf(args[1])) { auto pos = IntPos::extractPos(args[1]); bpos = pos->getBlockPos(); dimid = pos->getDimensionId(); } else if (IsInstanceOf(args[1])) { auto pos = FloatPos::extractPos(args[1]); bpos = pos->getVec3(); dimid = pos->getDimensionId(); } else { CHECK_ARGS_COUNT(args, 4); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); CHECK_ARG_TYPE(args[3], ValueKind::kNumber); if (args.size() > 4) { CHECK_ARG_TYPE(args[4], ValueKind::kNumber); dimid = args[4].toInt(); } bpos = BlockPos(args[1].toInt(), args[2].toInt(), args[3].toInt()); } if (auto sp = SimulatedPlayer::create(name, bpos, dimid)) return PlayerClass::newPlayer(sp); else return Local(); } CATCH("Fail in " __FUNCTION__ "!") } SimulatedPlayer* PlayerClass::asSimulatedPlayer() { if (get()->isSimulatedPlayer()) { return static_cast(get()); } return nullptr; } Local PlayerClass::simulateSneak(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); return Boolean::newBoolean(sp->simulateSneak()); } CATCH("Fail in " __FUNCTION__ "!") } // bool simulateAttack(class Actor*); // bool simulateAttack(); Local PlayerClass::simulateAttack(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); if (args.size() == 0) return Boolean::newBoolean(sp->simulateAttack()); if (auto actor = EntityClass::tryExtractActor(args[0])) { if (!*actor) return Local(); return Boolean::newBoolean(sp->simulateAttack(*actor)); } LOG_WRONG_ARG_TYPE(); return Local(); } CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateDestroy(); // LIAPI // bool simulateDestroyBlock(class BlockPos const&, enum ScriptFacing); Local PlayerClass::simulateDestroy(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); if (args.size() == 0) return Boolean::newBoolean(sp->simulateDestroy()); int dimid = sp->getDimensionId(); BlockPos bpos; size_t index = 0; ScriptModuleMinecraft::ScriptFacing face = (ScriptModuleMinecraft::ScriptFacing)0; if (IsInstanceOf(args[0])) { auto pos = IntPos::extractPos(args[index]); if (dimid != pos->getDimensionId()) return Local(); bpos = pos->getBlockPos(); index = 1; } else if (IsInstanceOf(args[0])) { auto pos = FloatPos::extractPos(args[index]); if (dimid != pos->getDimensionId()) return Local(); bpos = pos->getVec3(); index = 1; } else if (IsInstanceOf(args[0])) { auto block = EngineScope::currentEngine()->getNativeInstance(args[0]); auto pos = IntPos::extractPos(block->getPos()); if (dimid != pos->getDimensionId()) return Local(); bpos = pos->getBlockPos(); index = 1; } #ifdef ENABLE_NUMBERS_AS_POS else if (args[0].isNumber()) { CHECK_ARGS_COUNT(args, 4); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); bpos = {args[0].toInt(), args[1].toInt(), args[2].toInt()}; index = 3; } #endif // ENABLE_NUMBERS_AS_POS else { LOG_WRONG_ARG_TYPE(); return Local(); } if (args.size() > index) { CHECK_ARG_TYPE(args[index], ValueKind::kNumber); face = (ScriptModuleMinecraft::ScriptFacing)args[index].toInt(); } // TODO return Boolean::newBoolean(sp->simulateDestroyBlock(bpos, face)); } CATCH("Fail in " __FUNCTION__ "!") }; // void simulateDisconnect(); Local PlayerClass::simulateDisconnect(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); sp->simulateDisconnect(); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateInteract(class Actor&); // bool simulateInteract(class BlockPos const&, enum ScriptFacing); // bool simulateInteract(); Local PlayerClass::simulateInteract(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); if (args.size() == 0) return Boolean::newBoolean(sp->simulateInteract()); if (auto actor = EntityClass::tryExtractActor(args[0])) { if (!*actor) return Local(); return Boolean::newBoolean(sp->simulateInteract(**actor)); } int dimid = sp->getDimensionId(); BlockPos bpos; size_t index = 0; ScriptModuleMinecraft::ScriptFacing face = (ScriptModuleMinecraft::ScriptFacing)0; if (IsInstanceOf(args[0])) { auto pos = IntPos::extractPos(args[index]); if (dimid != pos->getDimensionId()) return Local(); bpos = pos->getBlockPos(); index = 1; } else if (IsInstanceOf(args[0])) { auto pos = FloatPos::extractPos(args[index]); if (dimid != pos->getDimensionId()) return Local(); bpos = pos->getVec3(); index = 1; } else if (IsInstanceOf(args[0])) { auto block = EngineScope::currentEngine()->getNativeInstance(args[0]); auto pos = IntPos::extractPos(block->getPos()); if (dimid != pos->getDimensionId()) return Local(); bpos = pos->getBlockPos(); index = 1; } #ifdef ENABLE_NUMBERS_AS_POS else if (args[0].isNumber()) { CHECK_ARGS_COUNT(args, 4); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); bpos = {args[0].toInt(), args[1].toInt(), args[2].toInt()}; index = 3; } #endif // ENABLE_NUMBERS_AS_POS else { LOG_WRONG_ARG_TYPE(); return Local(); } // TODO return Boolean::newBoolean(sp->simulateInteract(bpos, face)); } CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateJump(); Local PlayerClass::simulateJump(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); return Boolean::newBoolean(sp->simulateJump()); } CATCH("Fail in " __FUNCTION__ "!") }; // void simulateLocalMove(class Vec3 const&, float); Local PlayerClass::simulateLocalMove(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); Vec3 target; float speed = 1.0f; size_t index = 0; if (IsInstanceOf(args[0])) { auto pos = IntPos::extractPos(args[0]); target = pos->getBlockPos().toVec3(); index += 1; } else if (IsInstanceOf(args[0])) { auto pos = FloatPos::extractPos(args[0]); target = pos->getVec3(); index += 1; } #ifdef ENABLE_NUMBERS_AS_POS else if (args[0].isNumber()) { CHECK_ARGS_COUNT(args, 3); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); index += 3; } #endif // ENABLE_NUMBERS_AS_POS else { LOG_WRONG_ARG_TYPE(); return Local(); } if (args.size() > index) { CHECK_ARG_TYPE(args[index], ValueKind::kNumber); speed = args[index].asNumber().toFloat(); } sp->simulateLocalMove(target, speed); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") } // void simulateWorldMove(class Vec3 const&, float); Local PlayerClass::simulateWorldMove(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); Vec3 target; float speed = 1.0f; size_t index = 0; if (IsInstanceOf(args[0])) { auto pos = IntPos::extractPos(args[0]); target = pos->getBlockPos().toVec3(); index += 1; } else if (IsInstanceOf(args[0])) { auto pos = FloatPos::extractPos(args[0]); target = pos->getVec3(); index += 1; } #ifdef ENABLE_NUMBERS_AS_POS else if (args[0].isNumber()) { CHECK_ARGS_COUNT(args, 3); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); index += 3; } #endif // ENABLE_NUMBERS_AS_POS else { LOG_WRONG_ARG_TYPE(); return Local(); } if (args.size() > index) { CHECK_ARG_TYPE(args[index], ValueKind::kNumber); speed = args[index].asNumber().toFloat(); } sp->simulateWorldMove(target, speed); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; // void simulateMoveToLocation(class Vec3 const&, float); Local PlayerClass::simulateMoveTo(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); Vec3 target; float speed = 1.0f; size_t index = 0; if (IsInstanceOf(args[0])) { auto pos = IntPos::extractPos(args[0]); target = pos->getBlockPos().toVec3(); index += 1; } else if (IsInstanceOf(args[0])) { auto pos = FloatPos::extractPos(args[0]); target = pos->getVec3(); index += 1; } #ifdef ENABLE_NUMBERS_AS_POS else if (args[0].isNumber()) { CHECK_ARGS_COUNT(args, 3); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); index += 3; } #endif // ENABLE_NUMBERS_AS_POS else { LOG_WRONG_ARG_TYPE(); return Local(); } if (args.size() > index) { CHECK_ARG_TYPE(args[index], ValueKind::kNumber); speed = args[index].asNumber().toFloat(); } sp->simulateMoveToLocation(target, speed); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; // void simulateLookAt(class Actor&); // void simulateLookAt(class BlockPos const&); // void simulateLookAt(class Vec3 const&); Local PlayerClass::simulateLookAt(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); Vec3 target; int dimid = sp->getDimensionId(); if (IsInstanceOf(args[0])) { auto pos = IntPos::extractPos(args[0]); auto did = pos->getDimensionId(); if (dimid == did || did < 0 || did > 2) { sp->simulateLookAt(pos->getBlockPos()); return Boolean::newBoolean(true); } logger.debug("Can't simulate look at other dimension!"); return Boolean::newBoolean(false); } else if (IsInstanceOf(args[0])) { auto pos = FloatPos::extractPos(args[0]); auto did = pos->getDimensionId(); if (dimid == did || did < 0 || did > 2) { sp->simulateLookAt(pos->getVec3()); return Boolean::newBoolean(true); } logger.debug("Can't simulate look at other dimension!"); return Boolean::newBoolean(false); } else if (IsInstanceOf(args[0])) { auto block = EngineScope::currentEngine()->getNativeInstance(args[0]); auto pos = IntPos::extractPos(block->getPos()); auto did = pos->getDimensionId(); if (dimid == did || did < 0 || did > 2) { sp->simulateLookAt(pos->getBlockPos()); return Boolean::newBoolean(true); } logger.debug("Can't simulate look at other dimension!"); return Boolean::newBoolean(false); } else if (auto actor = EntityClass::tryExtractActor(args[0])) { if (!*actor) return Local(); sp->simulateLookAt(**actor); return Boolean::newBoolean(true); } LOG_WRONG_ARG_TYPE(); return Local(); } CATCH("Fail in " __FUNCTION__ "!") }; // void simulateSetBodyRotation(float); Local PlayerClass::simulateSetBodyRotation(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); sp->simulateSetBodyRotation(args[0].asNumber().toFloat()); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") } // void simulateWorldMove(class Vec3 const&, float); // void simulateMoveToLocation(class Vec3 const&, float); inline Local NavigateResultToObject(ScriptModuleMinecraft::ScriptNavigationResult const& res) { auto obj = Object::newObject(); obj.set(String::newString("isFullPath"), Boolean::newBoolean(res.mIsFullPath)); auto path = Array::newArray(); for (auto& pos : res.mPath) { path.add(Array::newArray({Number::newNumber(pos.x), Number::newNumber(pos.y), Number::newNumber(pos.z)})); } obj.set(String::newString("path"), path); return obj; } // struct ScriptNavigationResult simulateNavigateToEntity(class Actor&, float); // struct ScriptNavigationResult simulateNavigateToLocation(class Vec3 const&, float); // void simulateNavigateToLocations(std::vector&&, float); Local PlayerClass::simulateNavigateTo(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); float speed = 1.f; if (args.size() > 1) { CHECK_ARG_TYPE(args[1], ValueKind::kNumber); speed = args[1].asNumber().toFloat(); } if (args[0].isArray()) { auto arr = args[0].asArray(); std::vector path; for (size_t index = 0; index < arr.size(); ++index) { if (IsInstanceOf(arr.get(index))) path.emplace_back(IntPos::extractPos(arr.get(index))->getBlockPos().center()); else if (IsInstanceOf(arr.get(index))) path.emplace_back(FloatPos::extractPos(arr.get(index))->getVec3()); else if (arr.get(index).isArray()) { auto posArr = arr.get(index).asArray(); if (posArr.size() != 3 || !posArr.get(0).isNumber()) { LOG_WRONG_ARG_TYPE(); return Local(); } path.emplace_back(posArr.get(0).asNumber().toFloat(), posArr.get(1).asNumber().toFloat(), posArr.get(2).asNumber().toFloat()); } else { LOG_WRONG_ARG_TYPE(); return Local(); } } sp->simulateNavigateToLocations(std::move(path), speed); return Boolean::newBoolean(true); } else if (auto actor = EntityClass::tryExtractActor(args[0])) { if (!*actor) return Local(); auto res = sp->simulateNavigateToEntity(**actor, speed); return NavigateResultToObject(res); } else if (IsInstanceOf(args[0]) || IsInstanceOf(args[0])) { Vec3 pos = IsInstanceOf(args[0]) ? IntPos::extractPos(args[0])->getBlockPos().bottomCenter() : FloatPos::extractPos(args[0])->getVec3(); auto res = sp->simulateNavigateToLocation(pos, speed); return NavigateResultToObject(res); } #ifdef ENABLE_NUMBERS_AS_POS else if (args[0].isNumber()) { CHECK_ARGS_COUNT(args, 3); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kNumber); CHECK_ARG_TYPE(args[2], ValueKind::kNumber); if (args.size() > 3) { CHECK_ARG_TYPE(args[3], ValueKind::kNumber); speed = args[3].asNumber().toFloat(); } Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); auto res = sp->simulateNavigateToLocation(pos, speed); return NavigateResultToObject(res); } #endif // ENABLE_NUMBERS_AS_POS else { LOG_WRONG_ARG_TYPE(); return Local(); } } CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateSetItem(class ItemStack&, bool, int); // bool simulateUseItem(); // bool simulateUseItemInSlot(int); // bool simulateUseItem(class ItemStack&); // bool simulateUseItemInSlotOnBlock(int, class BlockPos const&, enum ScriptFacing, class Vec3 const&); // bool simulateUseItemOnBlock(class ItemStack&, class BlockPos const&, enum ScriptFacing, class Vec3 const&); Local PlayerClass::simulateUseItem(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); if (args.size() == 0) return Boolean::newBoolean(sp->simulateUseItem()); int slot = -1; ItemStack* item = nullptr; if (args[0].isNumber()) slot = args[0].toInt(); else if (IsInstanceOf(args[0])) item = ItemClass::extract(args[0]); else { LOG_WRONG_ARG_TYPE(); return Local(); } if (args.size() == 1) { if (item) return Boolean::newBoolean(sp->simulateUseItem(*item)); else return Boolean::newBoolean(sp->simulateUseItemInSlot(slot)); } BlockPos bpos; ScriptModuleMinecraft::ScriptFacing face = (ScriptModuleMinecraft::ScriptFacing)0; Vec3 relativePos = {0.5, 0.5, 0.5}; if (IsInstanceOf(args[1])) bpos = IntPos::extractPos(args[1])->getBlockPos(); else if (IsInstanceOf(args[1])) bpos = FloatPos::extractPos(args[1])->getVec3(); else { LOG_WRONG_ARG_TYPE(); return Local(); } if (args.size() > 2) { CHECK_ARG_TYPE(args[2], ValueKind::kNumber); face = (ScriptModuleMinecraft::ScriptFacing)args[2].toInt(); if (args.size() > 3) { if (IsInstanceOf(args[3])) { relativePos = FloatPos::extractPos(args[3])->getVec3(); } else { LOG_WRONG_ARG_TYPE(); return Local(); } } } if (item) return Boolean::newBoolean(sp->simulateUseItemOnBlock(*item, bpos, face, relativePos)); else return Boolean::newBoolean(sp->simulateUseItemInSlotOnBlock(slot, bpos, face, relativePos)); } CATCH("Fail in " __FUNCTION__ "!") }; // void simulateStopDestroyingBlock(); // void simulateStopInteracting(); // void simulateStopMoving(); // void simulateStopUsingItem(); Local PlayerClass::simulateStopDestroyingBlock(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); sp->simulateStopDestroyingBlock(); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; Local PlayerClass::simulateStopInteracting(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); sp->simulateStopInteracting(); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; Local PlayerClass::simulateStopMoving(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); sp->simulateStopMoving(); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; Local PlayerClass::simulateStopUsingItem(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); sp->simulateStopUsingItem(); return Boolean::newBoolean(true); } CATCH("Fail in " __FUNCTION__ "!") }; Local PlayerClass::simulateStopSneaking(const Arguments& args) { try { auto sp = asSimulatedPlayer(); if (!sp) return Local(); return Boolean::newBoolean(sp->simulateStopSneaking()); } CATCH("Fail in " __FUNCTION__ "!") }