#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Actor* Level::getEntity(ActorUniqueID uniqueId) { try { return SymCall("?fetchEntity@Level@@QEBAPEAVActor@@UActorUniqueID@@_N@Z", Actor*, Level*, ActorUniqueID)(Global, uniqueId); } catch (...) { return nullptr; } } BlockSource* Level::getBlockSource(int dimID) { // auto dim = Global->createDimension(dimID); auto dim = Global->getDimension(dimID); return &dim->getBlockSourceFromMainChunkSource(); //return dAccess(dim, 96); } BlockSource* Level::getBlockSource(Actor* ac) { return const_cast(&ac->getRegionConst()); } Block* Level::getBlock(BlockPos* pos, int dimId) { return getBlock(*pos, Level::getBlockSource(dimId)); } Block* Level::getBlock(BlockPos* pos, BlockSource* blockSource) { return (Block*)&(blockSource->getBlock(*pos)); } Block* Level::getBlock(const BlockPos& pos, int dimId) { return getBlock(pos, Level::getBlockSource(dimId)); } Block* Level::getBlock(const BlockPos& pos, BlockSource* blockSource) { return (Block*)&(blockSource->getBlock(pos)); } // Return nullptr when failing to get block // Block* Level::getBlockEx(const BlockPos& pos, int dimId) { // auto dim = Global->getDimension(dimId); // if (!dim) // return nullptr; // auto bs = &dim->getBlockSourceFromMainChunkSource(); // auto lc = bs->getChunkAt(pos); // if (!lc) // return nullptr; // short minHeight = dim->getMinHeight(); // if (pos.y < minHeight || pos.y > dim->getHeight()) // return nullptr; // ChunkBlockPos cbpos = ChunkBlockPos(pos, minHeight); // return const_cast(&lc->getBlock(cbpos)); // } BlockInstance Level::getBlockInstance(BlockPos* pos, int dimId) { return {*pos, dimId}; } BlockInstance Level::getBlockInstance(BlockPos* pos, BlockSource* blockSource) { return {*pos, blockSource->getDimensionId()}; } BlockInstance Level::getBlockInstance(const BlockPos& pos, int dim) { return {pos, dim}; } BlockInstance Level::getBlockInstance(const BlockPos& pos, BlockSource* blockSource) { return {pos, blockSource->getDimensionId()}; } BlockActor* Level::getBlockEntity(BlockPos* pos, int dimId) { return getBlockEntity(pos, Level::getBlockSource(dimId)); } BlockActor* Level::getBlockEntity(BlockPos* pos, BlockSource* blockSource) { return blockSource->getBlockEntity(*pos); } BlockActor* Level::getBlockEntity(const BlockPos& pos, int dimId) { return getBlockEntity((BlockPos*)&pos, Level::getBlockSource(dimId)); } BlockActor* Level::getBlockEntity(const BlockPos& pos, BlockSource* blockSource) { return getBlockEntity((BlockPos*)&pos, blockSource); } bool Level::setBlock(const BlockPos& pos, int dim, Block* block) { BlockSource* bs = getBlockSource(dim); return bs->setBlock(pos, *block, 3, nullptr, nullptr); // updateFlag = 3 from IDA SetBlockCommand::execute() } bool Level::setBlock(const BlockPos& pos, int dim, const string& name, unsigned short tileData) { Block* newBlock = Block::create(name, tileData); if (!newBlock) return false; return setBlock(pos, dim, newBlock); } bool Level::setBlock(const BlockPos& pos, int dim, CompoundTag* nbt) { Block* newBlock = Block::create(nbt); if (!newBlock) return false; return setBlock(pos, dim, newBlock); } // bool Level::breakBlockNaturally(BlockSource* bs, const BlockPos& pos) { // return getBlockInstance(pos, bs).breakNaturally(); // } // bool Level::breakBlockNaturally(BlockSource* bs, const BlockPos& pos, ItemStack* item) { // return getBlockInstance(pos, bs).breakNaturally(item); // } bool Level::hasContainer(Vec3 pos, int dim) { return getContainer(pos, dim) != nullptr; } Container* Level::getContainer(Vec3 pos, int dim) { // VirtualCall(getBlockEntity(), 224); // IDA ChestBlockActor::`vftable'{for `RandomizableBlockActorContainerBase'} // This function didn't use 'this' pointer return ((DropperBlockActor*)nullptr)->_getContainerAt(*Level::getBlockSource(dim), pos); } Actor* Level::getDamageSourceEntity(ActorDamageSource* ads) { ActorUniqueID v6 = ads->getDamagingEntityUniqueID(); return Global->getEntity(v6); } void* Level::ServerCommandOrigin::fake_vtbl[26]; CompoundTag& getServerOriginTag() { static auto cached = CompoundTag::fromSNBT(R"({"CommandPermissionLevel":4b,"DimensionId":"Overworld","OriginType":7b,"RequestId":"00000000-0000-0000-0000-000000000000"})"); return *cached; } std::unique_ptr getPlayerOriginTag(Player& player) { static auto cached = CompoundTag::fromSNBT(R"({"OriginType":0b,"PlayerId":0l})"); auto tag = cached->clone(); tag->putInt64("PlayerId", player.getUniqueID()); return std::move(tag); } // bool Level::executeCommand(const string& cmd) { // auto origin = ::ServerCommandOrigin::load(getServerOriginTag(), *Global); // return MinecraftCommands::_runcmd(std::move(origin), cmd); // } // std::unordered_map resultOfOrigin = {}; // std::pair Level::executeCommandEx(const string& cmd) { // auto origin = ::ServerCommandOrigin::load(getServerOriginTag(), *Global); // string val; // auto ptr = origin.get(); // resultOfOrigin[ptr] = &val; // bool rv = MinecraftCommands::_runcmd(std::move(origin), cmd); // if (resultOfOrigin.count(ptr)) // resultOfOrigin.erase(ptr); // return {rv, std::move(val)}; // } // static void* FAKE_PORGVTBL[26]; // bool Level::executeCommandAs(Player* pl, const string& cmd) { // auto tag = getPlayerOriginTag(*pl); // auto origin = PlayerCommandOrigin::load(*tag, *Global); // return MinecraftCommands::_runcmd(std::move(origin), cmd); // } std::vector Level::getAllPlayers() { try { std::vector player_list; Global->forEachPlayer([&](Player& sp) -> bool { Player* player = &sp; player_list.push_back(player); return true; }); return player_list; } catch (...) { return {}; } } std::vector Level::getAllEntities(int dimId) { try { Level* lv = Global; Dimension* dim = lv->getDimension(dimId); if (!dim) return {}; auto& list = *(std::unordered_map*)((uintptr_t)dim + 320); // IDA Dimension::registerEntity // Check Valid std::vector result; auto currTick = SymCall("?getCurrentTick@Level@@QEBAAEBUTick@@XZ", Tick*, Level*)(lv)->t; for (auto& i : list) { // auto entity = SymCall("??$tryUnwrap@VActor@@$$V@WeakEntityRef@@QEBAPEAVActor@@XZ", // Actor*, void*)(&i.second); auto entity = getEntity(i.first); if (!entity) continue; auto lastTick = entity->getLastTick(); if (!lastTick) continue; if (currTick - lastTick->t == 0 || currTick - lastTick->t == 1) result.push_back(entity); } return result; } catch (...) { return {}; } } std::vector Level::getAllEntities() { std::vector entityList; auto entities = getAllEntities(0); entityList.insert(entityList.end(), entities.begin(), entities.end()); entities = getAllEntities(1); entityList.insert(entityList.end(), entities.begin(), entities.end()); entities = getAllEntities(2); entityList.insert(entityList.end(), entities.begin(), entities.end()); return entityList; //return Global->getRuntimeActorList(); } Player* Level::getPlayer(const string& info) { string target{info}; std::transform(target.begin(), target.end(), target.begin(), ::tolower); // lower case the string size_t delta = UINT64_MAX; // c++ int max Player* found = nullptr; Global->forEachPlayer([&](Player& sp) -> bool { Player* p = &sp; if (p->getXuid() == target || p->getRealName() == info) { found = p; return false; } string pName = p->getRealName(); std::transform(pName.begin(), pName.end(), pName.begin(), ::tolower); //模糊匹配 if (pName.find(target) == 0) { // 0 ís the index where the "target" appear in "pName" size_t curDelta = pName.length() - target.length(); if (curDelta == 0) { found = p; } if (curDelta < delta) { found = p; delta = curDelta; } } return true; }); return found; } Player* Level::getPlayer(ActorUniqueID id) { // 裂开,这个符号也没有 Actor* actor = Level::fetchEntity(id,0); if(actor && actor->hasCategory((ActorCategory)1)) return (Player*)actor; else return nullptr; //return SymCall("?getPlayer@Level@@UEBAPEAVPlayer@@UActorUniqueID@@@Z", Player*, Level*, ActorUniqueID)(Global, id); } // Actor* Level::spawnMob(Vec3 pos, int dimId, std::string name) { // Spawner* sp = &Global->getSpawner(); // return sp->spawnMob(pos, dimId, std::move(name)); // } // Actor* Level::cloneMob(Vec3 pos, int dimId, Actor* ac) { // Spawner* sp = &Global->getSpawner(); // Mob* mob = sp->spawnMob(pos, dimId, std::move(ac->getTypeName())); // mob->setNbt(ac->getNbt().get()); // return mob; // } // Actor* Level::spawnItem(Vec3 pos, int dimId, ItemStack* item) { // Spawner* sp = &Global->getSpawner(); // return sp->spawnItem(pos, dimId, item); // } bool Level::createExplosion(Vec3 pos, int dimId, Actor* source, float radius, bool createFire, bool canBreak, float maxResistance) { Global->explode(*Level::getBlockSource(dimId), source, pos, radius, createFire, canBreak, maxResistance, false); return true; } #include ItemStack* Level::getItemStackFromId(short itemId, int aux) { auto item = ItemRegistry::getItem(itemId); if (item) return new ItemStack(*item, 1, aux); return nullptr; } void Level::broadcastText(const string& a1, TextType ty) { if (!Global) return; Global->forEachPlayer([&](Player& sp) -> bool { sp.sendTextPacket(a1, ty); return true; }); } void Level::broadcastTitle(const string& text, TitleType Type, int FadeInDuration, int RemainDuration, int FadeOutDuration) { if (!Global) return; Global->forEachPlayer([&](Player& sp) -> bool { sp.sendTitlePacket(text, Type, FadeInDuration, RemainDuration, FadeOutDuration); return true; }); } void Level::sendPacketForAllPlayers(Packet& pkt) { if (!Global) return; auto sender = (LoopbackPacketSender*)Global->getPacketSender(); if (sender) return sender->sendBroadcast(pkt); } // For compatibility void Level::sendPacketForAllPlayer(Packet& pkt) { sendPacketForAllPlayers(pkt); } // std::string Level::getCurrentLevelName() { // if (Global) // return Global->getLevelName(); // std::ifstream fin("server.properties"); // string buf; // while (getline(fin, buf)) { // if (buf.find("level-name=") != string::npos) { // if (buf.back() == '\n') // buf.pop_back(); // if (buf.back() == '\r') // buf.pop_back(); // return buf.substr(11); // } // } // return ""; // } // std::string Level::getCurrentLevelPath() { // return "./worlds/" + getCurrentLevelName(); // } int64_t BossID = 7492341231332ull; int64_t Level::createBossEvent() { return ++BossID; }