#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)); } BlockPalette* Level::getBlockPalettePtr(){ // MovingBlockActor::load Line69 return dAccess(Global,2000); }; // 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->getHeight(); 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); std::string requestID = "00000000-0000-0000-0000-000000000000"; std::unique_ptr origin(new ServerCommandOrigin(requestID,*Global, CommandPermissionLevel(4))); return MinecraftCommands::_runcmd(std::move(origin), cmd); } std::unordered_map resultOfOrigin = {}; std::pair Level::executeCommandEx(const string& cmd) { //auto origin = ::ServerCommandOrigin::load(getServerOriginTag(), *Global); const std::string requestID = "00000000-0000-0000-0000-000000000000"; std::unique_ptr origin(new ServerCommandOrigin(requestID,*Global, CommandPermissionLevel(4))); 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); std::unique_ptr origin(new PlayerCommandOrigin(*pl)); 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); } Player* Level::getPlayer(const mce::UUID& uuid) const{ // 根据函数 // std::_Func_impl_no_alloc__lambda_71cde901375eb38deb56f48a96514d77__bool_Player_const___::_Do_call Player* findPlayer = this->findPlayer([&](const Player& pl)->bool { if (pl.getClientUUID() == uuid) return true; return false; }); return findPlayer; } 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; }