#pragma once #include "TestManager.hpp" #include #include #include #include #include #include #include #include template std::unique_ptr SetupTestBot(const Botcraft::Vector3& offset = { 0,0,0 }, const Botcraft::GameType gamemode = Botcraft::GameType::Survival) { std::string botname; std::unique_ptr bot = TestManager::GetInstance().GetBot(botname, gamemode); const Botcraft::Vector3 pos = offset + TestManager::GetInstance().GetCurrentOffset(); TestManager::GetInstance().Teleport(botname, pos); // Wait for bot to register teleportation std::shared_ptr local_player = bot->GetLocalPlayer(); if (!Botcraft::Utilities::WaitForCondition([&]() { return local_player->GetPosition().SqrDist(pos) < 1.0; }, 5000)) { throw std::runtime_error("Timeout waiting " + botname + " to register teleportation"); } // Wait for bot to load center and corner view_distance blocks std::shared_ptr world = bot->GetWorld(); const int chunk_x = static_cast(std::floor(pos.x / static_cast(Botcraft::CHUNK_WIDTH))); const int chunk_z = static_cast(std::floor(pos.z / static_cast(Botcraft::CHUNK_WIDTH))); // -1 because sometimes corner chunks are not sent, depending on where you are on the current chunk const int view_distance = MinecraftServer::options.view_distance - 1; std::vector> wait_loaded = { {chunk_x * Botcraft::CHUNK_WIDTH, chunk_z * Botcraft::CHUNK_WIDTH}, {(chunk_x + view_distance) * Botcraft::CHUNK_WIDTH - 1, (chunk_z + view_distance) * Botcraft::CHUNK_WIDTH - 1}, {(chunk_x - view_distance) * Botcraft::CHUNK_WIDTH, (chunk_z + view_distance) * Botcraft::CHUNK_WIDTH - 1}, {(chunk_x + view_distance) * Botcraft::CHUNK_WIDTH - 1, (chunk_z - view_distance) * Botcraft::CHUNK_WIDTH}, {(chunk_x - view_distance) * Botcraft::CHUNK_WIDTH, (chunk_z - view_distance) * Botcraft::CHUNK_WIDTH} }; if (!Botcraft::Utilities::WaitForCondition([&]() { for (size_t i = 0; i < wait_loaded.size(); ++i) { if (!bot->GetWorld()->IsLoaded(Botcraft::Position(wait_loaded[i].first, 2, wait_loaded[i].second))) { return false; } } return true; }, 15000)) { throw std::runtime_error("Timeout waiting " + botname + " to load surroundings"); } return bot; } #include #include #include template bool GiveItem(std::unique_ptr& bot, const std::string& item_name, const std::string& item_pretty_name, const int quantity = 1) { const std::shared_ptr inventory_manager = bot->GetInventoryManager(); const Botcraft::Item* item = Botcraft::AssetsManager::getInstance().GetItem(Botcraft::AssetsManager::getInstance().GetItemID(item_name)); short receiving_slot = -1; const std::map slots = inventory_manager->GetPlayerInventory()->GetSlots(); for (short i = Botcraft::Window::INVENTORY_HOTBAR_START; i < Botcraft::Window::INVENTORY_OFFHAND_INDEX; ++i) { if (slots.at(i).IsEmptySlot() || (item->GetId() == slots.at(i).GetItemID() && item->GetStackSize() >= slots.at(i).GetItemCount() + quantity)) { receiving_slot = i; break; } } // No slot available in the hotbar, check the main inventory if (receiving_slot == -1) { for (short i = Botcraft::Window::INVENTORY_STORAGE_START; i < Botcraft::Window::INVENTORY_HOTBAR_START; ++i) { if (slots.at(i).IsEmptySlot()) { receiving_slot = i; break; } } } if (receiving_slot == -1) { return false; } const std::string& botname = bot->GetNetworkManager()->GetMyName(); MinecraftServer::GetInstance().SendLine("give " + botname + " " + item_name + " " + std::to_string(quantity)); MinecraftServer::GetInstance().WaitLine(".*?: (?:Given|Gave " + std::to_string(quantity) + ") \\[" + item_pretty_name + "\\](?: \\* " + std::to_string(quantity) + ")? to " + botname + ".*", 5000); return Botcraft::Utilities::WaitForCondition([&]() { return !bot->GetInventoryManager()->GetPlayerInventory()->GetSlot(receiving_slot).IsEmptySlot(); }, 5000); }