diff --git a/external/libutil b/external/libutil index b822525119..48b813d04b 160000 --- a/external/libutil +++ b/external/libutil @@ -1 +1 @@ -Subproject commit b82252511945ca49599299ed6ae1accbb96c1762 +Subproject commit 48b813d04b8651b9d9bca7472b03df2e35719bf5 diff --git a/extras/ai-battle/HeadlessGame.cpp b/extras/ai-battle/HeadlessGame.cpp index 86c544ca25..444b9e8b92 100644 --- a/extras/ai-battle/HeadlessGame.cpp +++ b/extras/ai-battle/HeadlessGame.cpp @@ -157,8 +157,8 @@ void HeadlessGame::RecordReplay(const bfs::path& path, unsigned random_init) mapInfo.luaData.CompressFromFile(luaPath_, &mapInfo.luaChecksum); } - for(unsigned playerId = 0; playerId < world_.GetNumPlayers(); ++playerId) - replay_.AddPlayer(world_.GetPlayer(playerId)); + for(auto& player : world_.getPlayers()) + replay_.AddPlayer(player); replay_.ggs = game_.ggs_; if(!replay_.StartRecording(path, mapInfo, random_init)) throw std::runtime_error("Replayfile could not be opened!"); @@ -170,8 +170,8 @@ void HeadlessGame::SaveGame(const bfs::path& path) const bfs::remove(path); Savegame save; - for(unsigned playerId = 0; playerId < world_.GetNumPlayers(); ++playerId) - save.AddPlayer(world_.GetPlayer(playerId)); + for(auto& player : world_.getPlayers()) + save.AddPlayer(player); save.ggs = game_.ggs_; save.ggs.exploration = Exploration::Disabled; // no FOW save.start_gf = em_.GetCurrentGF(); @@ -220,9 +220,8 @@ void HeadlessGame::PrintState() printConsole("┌────────────────────────┬─────────────────┬─────────────┬───────────┬───────────┐\n"); printConsole("│ Player │ Country │ Buildings │ Military │ Gold │\n"); printConsole("├────────────────────────┼─────────────────┼─────────────┼───────────┼───────────┤\n"); - for(unsigned playerId = 0; playerId < world_.GetNumPlayers(); ++playerId) + for(const auto& player : world_.getPlayers()) { - const GamePlayer& player = world_.GetPlayer(playerId); printConsole("│ %s%-22s%s │ %15s │ %11s │ %9s │ %9s │\n", player.IsDefeated() ? "\x1b[9m" : "", player.name.c_str(), player.IsDefeated() ? "\x1b[29m" : "", HumanReadableNumber(player.GetStatisticCurrentValue(StatisticType::Country)).c_str(), diff --git a/libs/s25main/Game.cpp b/libs/s25main/Game.cpp index 02b3fdea3e..d855f8ed80 100644 --- a/libs/s25main/Game.cpp +++ b/libs/s25main/Game.cpp @@ -61,9 +61,9 @@ namespace { unsigned getNumAlivePlayers(const GameWorldBase& world) { unsigned numPlayersAlive = 0; - for(unsigned i = 0; i < world.GetNumPlayers(); ++i) + for(const auto& player : world.getPlayers()) { - if(!world.GetPlayer(i).IsDefeated()) + if(!player.IsDefeated()) ++numPlayersAlive; } return numPlayersAlive; @@ -76,9 +76,8 @@ void Game::RunGF() // EventManager Bescheid sagen em_->ExecuteNextGF(); // Notfallprogramm durchlaufen lassen - for(unsigned i = 0; i < world_.GetNumPlayers(); ++i) + for(GamePlayer& player : world_.getPlayers()) { - GamePlayer& player = world_.GetPlayer(i); if(player.isUsed()) { // Auf Notfall testen (Wenige Bretter/Steine und keine Holzindustrie) @@ -100,8 +99,8 @@ void Game::RunGF() void Game::StatisticStep() { - for(unsigned i = 0; i < world_.GetNumPlayers(); ++i) - world_.GetPlayer(i).StatisticStep(); + for(auto& player : world_.getPlayers()) + player.StatisticStep(); CheckObjective(); } diff --git a/libs/s25main/GamePlayer.cpp b/libs/s25main/GamePlayer.cpp index c444ebc90e..d4e9050b68 100644 --- a/libs/s25main/GamePlayer.cpp +++ b/libs/s25main/GamePlayer.cpp @@ -889,6 +889,12 @@ void GamePlayer::FindWarehouseForAllJobs(const Job job) } } +static bool IsWareFineWithEmergencyProtocol(GoodType goodType, const noBaseBuilding& goal) +{ + return (goodType != GoodType::Boards && goodType != GoodType::Stones) + || goal.GetBuildingType() == BuildingType::Woodcutter || goal.GetBuildingType() == BuildingType::Sawmill; +} + Ware* GamePlayer::OrderWare(const GoodType ware, noBaseBuilding& goal) { /// Gibt es ein Lagerhaus mit dieser Ware? @@ -902,8 +908,7 @@ Ware* GamePlayer::OrderWare(const GoodType ware, noBaseBuilding& goal) else { // Wenn Notfallprogramm aktiv nur an Holzfäller und Sägewerke Bretter/Steine liefern - if((ware != GoodType::Boards && ware != GoodType::Stones) - || goal.GetBuildingType() == BuildingType::Woodcutter || goal.GetBuildingType() == BuildingType::Sawmill) + if(IsWareFineWithEmergencyProtocol(ware, goal)) return wh->OrderWare(ware, goal); else return nullptr; @@ -2089,6 +2094,23 @@ bool GamePlayer::FindHarborForUnloading(noShip* ship, const MapPoint start, Harb return false; } +void GamePlayer::CancelWaresForEmergencyProtocol() +{ + for(auto it = ware_list.begin(); it != ware_list.end();) + { + Ware* ware = *it; + if(ware->IsWaitingInWarehouse() && ware->GetGoal() + && !IsWareFineWithEmergencyProtocol(ware->type, *ware->GetGoal())) + { + ware->NotifyGoalAboutLostWare(); + static_cast(ware->GetLocation())->CancelWare(ware); + it = ware_list.erase(it); + continue; + } + it++; + } +} + void GamePlayer::TestForEmergencyProgramm() { // we are already defeated, do not even think about an emergency program - it's too late :-( @@ -2118,6 +2140,9 @@ void GamePlayer::TestForEmergencyProgramm() emergency = true; SendPostMessage(std::make_unique( world.GetEvMgr().GetCurrentGF(), _("The emergency program has been activated."), PostCategory::Economy)); + + // Handle wares already ordered + CancelWaresForEmergencyProtocol(); } } else { diff --git a/libs/s25main/GamePlayer.h b/libs/s25main/GamePlayer.h index ada0ba552a..35207d77fc 100644 --- a/libs/s25main/GamePlayer.h +++ b/libs/s25main/GamePlayer.h @@ -331,6 +331,8 @@ class GamePlayer : public GamePlayerInfo const Statistic& GetStatistic(StatisticTime time) const { return statistic[time]; }; unsigned GetStatisticCurrentValue(StatisticType idx) const { return statisticCurrentData[idx]; } + // Stop wares restricted in emergency mode that are waiting in warehouse to be transported already + void CancelWaresForEmergencyProtocol(); // Testet ob Notfallprogramm aktiviert werden muss und tut dies dann void TestForEmergencyProgramm(); bool hasEmergency() const { return emergency; } diff --git a/libs/s25main/SerializedGameData.cpp b/libs/s25main/SerializedGameData.cpp index 1b0997c910..50ef81f662 100644 --- a/libs/s25main/SerializedGameData.cpp +++ b/libs/s25main/SerializedGameData.cpp @@ -258,13 +258,13 @@ void SerializedGameData::MakeSnapshot(const Game& game) PushObject(gw.getEconHandler(), true); } // Spieler serialisieren - for(unsigned i = 0; i < gw.GetNumPlayers(); ++i) + for(const auto& player : gw.getPlayers()) { if(debugMode) - LOG.write("Start serializing player %1% at %2%\n") % i % GetLength(); - gw.GetPlayer(i).Serialize(*this); + LOG.write("Start serializing player %1% at %2%\n") % player.GetPlayerId() % GetLength(); + player.Serialize(*this); if(debugMode) - LOG.write("Done serializing player %1% at %2%\n") % i % GetLength(); + LOG.write("Done serializing player %1% at %2%\n") % player.GetPlayerId() % GetLength(); } if(writtenEventIds.size() != writeEm->GetNumActiveEvents()) @@ -301,8 +301,8 @@ void SerializedGameData::ReadSnapshot(Game& game, ILocalGameState& localGameStat std::unique_ptr(PopObject(GO_Type::Economymodehandler))); } - for(unsigned i = 0; i < gw.GetNumPlayers(); ++i) - gw.GetPlayer(i).Deserialize(*this); + for(auto& player : gw.getPlayers()) + player.Deserialize(*this); // If this check fails, we did not serialize all objects or there was an async if(readEvents.size() != em->GetNumActiveEvents()) diff --git a/libs/s25main/ingameWindows/iwStatistics.cpp b/libs/s25main/ingameWindows/iwStatistics.cpp index 9ede3a7ead..360204744a 100644 --- a/libs/s25main/ingameWindows/iwStatistics.cpp +++ b/libs/s25main/ingameWindows/iwStatistics.cpp @@ -82,9 +82,9 @@ iwStatistics::iwStatistics(const GameWorldViewer& gwv) // Count active players numPlayingPlayers = 0; const GameWorldBase& world = gwv.GetWorld(); - for(const auto i : helpers::range(world.GetNumPlayers())) + for(const auto& player : world.getPlayers()) { - if(world.GetPlayer(i).isUsed()) + if(player.isUsed()) numPlayingPlayers++; } diff --git a/libs/s25main/network/GameClient.cpp b/libs/s25main/network/GameClient.cpp index 0060d5964f..4d9950a682 100644 --- a/libs/s25main/network/GameClient.cpp +++ b/libs/s25main/network/GameClient.cpp @@ -327,8 +327,8 @@ void GameClient::StartGame(const unsigned random_init) { RTTR_Assert(mapinfo.type != MapType::Savegame); /// Startbündnisse setzen - for(unsigned i = 0; i < gameWorld.GetNumPlayers(); ++i) - gameWorld.GetPlayer(i).MakeStartPacts(); + for(auto& player : gameWorld.getPlayers()) + player.MakeStartPacts(); MapLoader loader(gameWorld); if(!loader.Load(mapinfo.filepath) @@ -1580,8 +1580,8 @@ bool GameClient::StartReplay(const boost::filesystem::path& path) idx++; } - for(unsigned i = 0; i < game->world_.GetNumPlayers(); i++) - game->world_.GetPlayer(i).ChangeDistribution(newDistributions); + for(auto& player : game->world_.getPlayers()) + player.ChangeDistribution(newDistributions); } replayinfo->next_gf = replayinfo->replay.ReadGF(); diff --git a/libs/s25main/world/GameWorldBase.cpp b/libs/s25main/world/GameWorldBase.cpp index 38363427fc..b0578519c4 100644 --- a/libs/s25main/world/GameWorldBase.cpp +++ b/libs/s25main/world/GameWorldBase.cpp @@ -66,6 +66,16 @@ unsigned GameWorldBase::GetNumPlayers() const return players.size(); } +s25util::span GameWorldBase::getPlayers() +{ + return players; +} + +s25util::span GameWorldBase::getPlayers() const +{ + return players; +} + bool GameWorldBase::IsSinglePlayer() const { bool foundPlayer = false; diff --git a/libs/s25main/world/GameWorldBase.h b/libs/s25main/world/GameWorldBase.h index 3d5ff465d6..1a4e1f0265 100644 --- a/libs/s25main/world/GameWorldBase.h +++ b/libs/s25main/world/GameWorldBase.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org) // // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,6 +12,7 @@ #include "notifications/NotificationManager.h" #include "postSystem/PostManager.h" #include "world/World.h" +#include "s25util/span.hpp" #include #include #include @@ -158,6 +159,8 @@ class GameWorldBase : public World GamePlayer& GetPlayer(unsigned id); const GamePlayer& GetPlayer(unsigned id) const; unsigned GetNumPlayers() const; + s25util::span getPlayers(); + s25util::span getPlayers() const; bool IsSinglePlayer() const; /// Return the game settings const GlobalGameSettings& GetGGS() const { return gameSettings; } diff --git a/tests/s25Main/autoplay/main.cpp b/tests/s25Main/autoplay/main.cpp index bc83245bd6..1558a7a9db 100644 --- a/tests/s25Main/autoplay/main.cpp +++ b/tests/s25Main/autoplay/main.cpp @@ -88,8 +88,8 @@ static void playReplay(const boost::filesystem::path& replayPath, const bool isS BOOST_TEST_REQUIRE(replay.GetMinorVersion() < 3u); MapLoader::SetupResources(gameWorld, false); - for(unsigned i = 0; i < gameWorld.GetNumPlayers(); ++i) - gameWorld.GetPlayer(i).MakeStartPacts(); + for(auto& player : gameWorld.getPlayers()) + player.MakeStartPacts(); } gameWorld.InitAfterLoad(); diff --git a/tests/s25Main/integration/testArmor.cpp b/tests/s25Main/integration/testArmor.cpp index e18c13a3fa..d78b570889 100644 --- a/tests/s25Main/integration/testArmor.cpp +++ b/tests/s25Main/integration/testArmor.cpp @@ -83,10 +83,10 @@ struct ArmorTradeFixture : public ArmoredSoldierFixture void testExpectedFiguresInGlobalInventoryMatchWithHQInventory() const { - for(unsigned i = 0; i < world.GetNumPlayers(); i++) + for(const auto& player : world.getPlayers()) { - auto const& playerWh = world.GetSpecObj(players[i]->GetHQPos()); - auto const& globalInventoryPlayer = world.GetPlayer(i).GetInventory(); + auto const& playerWh = world.GetSpecObj(player.GetHQPos()); + auto const& globalInventoryPlayer = player.GetInventory(); for(unsigned i = 0; i < NUM_SOLDIER_RANKS; i++) { BOOST_TEST(playerWh->GetNumRealArmoredFigures(jobEnumToAmoredSoldierEnum(SOLDIER_JOBS[i])) diff --git a/tests/s25Main/integration/testEconomyMode.cpp b/tests/s25Main/integration/testEconomyMode.cpp index e5ddac51ec..14d1cf5414 100644 --- a/tests/s25Main/integration/testEconomyMode.cpp +++ b/tests/s25Main/integration/testEconomyMode.cpp @@ -118,8 +118,8 @@ BOOST_FIXTURE_TEST_CASE(EconomyModeSerialization, EconModeFixture) world.getEconHandler()->UpdateAmounts(); Savegame save; - for(unsigned i = 0; i < world.GetNumPlayers(); i++) - save.AddPlayer(world.GetPlayer(i)); + for(const auto& player : world.getPlayers()) + save.AddPlayer(player); save.ggs = ggs; save.start_gf = game->em_->GetCurrentGF(); save.sgd.MakeSnapshot(*game); diff --git a/tests/s25Main/integration/testEmergencyProtocol.cpp b/tests/s25Main/integration/testEmergencyProtocol.cpp new file mode 100644 index 0000000000..162726be7e --- /dev/null +++ b/tests/s25Main/integration/testEmergencyProtocol.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "NodalObjectTypes.h" +#include "buildings/nobHQ.h" +#include "worldFixtures/WorldWithGCExecution.h" +#include "worldFixtures/initGameRNG.hpp" +#include + +/// Start with low wares and build 2 farms to trigger emergency protocol activation +struct EmergencyFixture : public WorldWithGCExecution1P +{ + nobHQ* hq = world.GetPlayer(0).GetHQ(); + EmergencyFixture() + { + hq->AddToInventory(hq->getStartInventory(StartWares::VLow), true); + MapPoint pos; + + pos = hqPos + MapPoint(3, 0); + world.SetBuildingSite(BuildingType::Farm, pos, 0); + BuildRoadForBlds(pos, hqPos); + + pos = hqPos + MapPoint(-3, 0); + world.SetBuildingSite(BuildingType::Farm, pos, 0); + BuildRoadForBlds(pos, hqPos); + + // wait until emergency protocol should be activated + RTTR_EXEC_TILL(500, hq->GetInventory()[GoodType::Boards] == 10); + + BOOST_TEST_REQUIRE(world.GetPlayer(0).hasEmergency()); + + // No more boards are carried out to the farms due to emergency protocol + RTTR_SKIP_GFS(200); + BOOST_TEST(hq->GetInventory()[GoodType::Boards] == 10); + + initGameRNG(); + } +}; + +BOOST_FIXTURE_TEST_SUITE(EmergencyProtocol, EmergencyFixture) +BOOST_AUTO_TEST_CASE(CanBuildWoodcutterAndSawmill) +{ + const MapPoint posWoodcutter = hqPos + MapPoint(-1, 2); + world.SetBuildingSite(BuildingType::Woodcutter, posWoodcutter, 0); + BuildRoadForBlds(posWoodcutter, hqPos); + + const MapPoint posSawmill = hqPos + MapPoint(-2, 4); + world.SetBuildingSite(BuildingType::Sawmill, posSawmill, 0); + BuildRoadForBlds(posSawmill, hqPos); + + // check if inventory boards are given out + RTTR_EXEC_TILL(200, hq->GetInventory()[GoodType::Boards] < 10); + + // check that buildings are built + RTTR_EXEC_TILL(2000, world.GetNO(posWoodcutter)->GetType() == NodalObjectType::Building); + RTTR_EXEC_TILL(2000, world.GetNO(posSawmill)->GetType() == NodalObjectType::Building); +} + +BOOST_FIXTURE_TEST_CASE(CannotBuildOtherBuldings, EmergencyFixture) +{ + const MapPoint pos = hqPos + MapPoint(-3, 0); + world.SetBuildingSite(BuildingType::Watchtower, pos, 0); + + BuildRoadForBlds(pos, hqPos); + + // No boards are carried out to the farms or watchtower due to emergency protocol + RTTR_SKIP_GFS(500); + BOOST_TEST(hq->GetInventory()[GoodType::Boards] == 10); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/tests/s25Main/integration/testGameCommands.cpp b/tests/s25Main/integration/testGameCommands.cpp index 22ba315bde..72c3363e82 100644 --- a/tests/s25Main/integration/testGameCommands.cpp +++ b/tests/s25Main/integration/testGameCommands.cpp @@ -738,8 +738,8 @@ void InitPactsAndPost(GameWorldBase& world) BOOST_FIXTURE_TEST_CASE(NotifyAllies, WorldWithGCExecution3P) { // At first there are no teams - for(unsigned i = 0; i < world.GetNumPlayers(); i++) - BOOST_TEST_REQUIRE(world.GetPlayer(i).team == Team::None); + for(const auto& player : world.getPlayers()) + BOOST_TEST_REQUIRE(player.team == Team::None); PostManager& postMgr = world.GetPostMgr(); // Add postbox for each player for(unsigned i = 0; i < world.GetNumPlayers(); i++) diff --git a/tests/s25Main/integration/testProduction.cpp b/tests/s25Main/integration/testProduction.cpp index 5ce05b76b4..e73014a1bb 100644 --- a/tests/s25Main/integration/testProduction.cpp +++ b/tests/s25Main/integration/testProduction.cpp @@ -74,7 +74,8 @@ BOOST_FIXTURE_TEST_CASE(MetalWorkerStopped, WorldWithGCExecution1P) BOOST_FIXTURE_TEST_CASE(MetalWorkerOrders, WorldWithGCExecution1P) { GoodsAndPeopleCounts inv; - inv[GoodType::Boards] = 10; + inv[GoodType::Boards] = 20; + inv[GoodType::Stones] = 20; inv[GoodType::Iron] = 10; inv[Job::Metalworker] = 1; world.GetSpecObj(hqPos)->AddToInventory(inv, true); diff --git a/tests/s25Main/integration/testSerialization.cpp b/tests/s25Main/integration/testSerialization.cpp index 0b06c034b4..a5bca55979 100644 --- a/tests/s25Main/integration/testSerialization.cpp +++ b/tests/s25Main/integration/testSerialization.cpp @@ -250,8 +250,8 @@ BOOST_FIXTURE_TEST_CASE(BaseSaveLoad, RandWorldFixture) Savegame save; - for(unsigned i = 0; i < world.GetNumPlayers(); i++) - save.AddPlayer(world.GetPlayer(i)); + for(const auto& player : world.getPlayers()) + save.AddPlayer(player); save.ggs = ggs; save.start_gf = em.GetCurrentGF(); @@ -563,8 +563,8 @@ BOOST_FIXTURE_TEST_CASE(ReplayWithSavegame, RandWorldFixture) map.filepath = "Map.swd"; map.luaFilepath = "Map.lua"; map.savegame = std::make_unique(); - for(unsigned i = 0; i < world.GetNumPlayers(); i++) - map.savegame->AddPlayer(world.GetPlayer(i)); + for(const auto& player : world.getPlayers()) + map.savegame->AddPlayer(player); // We can change players std::vector players(4); players[0].ps = PlayerState::AI; diff --git a/tests/s25Main/integration/testWorld.cpp b/tests/s25Main/integration/testWorld.cpp index dc25e23549..c38e2d784f 100644 --- a/tests/s25Main/integration/testWorld.cpp +++ b/tests/s25Main/integration/testWorld.cpp @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(HQPlacement) // The loader stores the HQ positions read from the map BOOST_TEST(hqsShuffledMap == hqsOriginalMap, boost::test_tools::per_element()); // When shuffled the positions should have changed - BOOST_TEST(hqsShuffledWorld != hqsOriginalWorld, boost::test_tools::per_element()); + BOOST_TEST(hqsShuffledWorld != hqsOriginalWorld); helpers::sort(hqsOriginalMap, MapPointLess{}); helpers::sort(hqsShuffledWorld, MapPointLess{}); helpers::sort(hqsOriginalWorld, MapPointLess{}); diff --git a/tests/s25Main/worldFixtures/TestEventManager.cpp b/tests/s25Main/worldFixtures/TestEventManager.cpp index 49a02e6766..b2f5f967d2 100644 --- a/tests/s25Main/worldFixtures/TestEventManager.cpp +++ b/tests/s25Main/worldFixtures/TestEventManager.cpp @@ -1,11 +1,13 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org) // // SPDX-License-Identifier: GPL-2.0-or-later #include "TestEventManager.h" #include "GameEvent.h" +#include "GamePlayer.h" +#include "world/GameWorldBase.h" -unsigned TestEventManager::ExecuteNextEvent(unsigned maxGF) +unsigned TestEventManager::doExecuteNextEvent(unsigned maxGF) { if(GetCurrentGF() >= maxGF) return 0; @@ -29,6 +31,23 @@ unsigned TestEventManager::ExecuteNextEvent(unsigned maxGF) return numGFs; } +unsigned TestEventManager::ExecuteNextEvent(unsigned maxGF) +{ + const auto numGFs = doExecuteNextEvent(maxGF); + if(numGFs > 0) + { + for(auto& player : world_->getPlayers()) + { + if(player.isUsed()) + { + player.TestForEmergencyProgramm(); + player.TestPacts(); + } + } + } + return numGFs; +} + std::vector TestEventManager::GetObjEvents(const GameObject& obj) const { std::vector objEvnts; diff --git a/tests/s25Main/worldFixtures/TestEventManager.h b/tests/s25Main/worldFixtures/TestEventManager.h index 020f836e44..6902252b83 100644 --- a/tests/s25Main/worldFixtures/TestEventManager.h +++ b/tests/s25Main/worldFixtures/TestEventManager.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org) // // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,8 +7,13 @@ #include "EventManager.h" #include +class GameWorldBase; + class TestEventManager : public EventManager { + GameWorldBase* world_ = nullptr; + unsigned doExecuteNextEvent(unsigned maxGF); + public: TestEventManager(unsigned startGF = 0) : EventManager(startGF) {} /// Execute the next event increasing the GF to the events GF @@ -22,4 +27,5 @@ class TestEventManager : public EventManager /// Remove the event and add a copy that is executed at the given GF const GameEvent* RescheduleEvent(const GameEvent* event, unsigned targetGF); std::vector GetEvents() const; + void setWorld(GameWorldBase& world) { world_ = &world; } }; diff --git a/tests/s25Main/worldFixtures/WorldFixture.h b/tests/s25Main/worldFixtures/WorldFixture.h index d7b9ae4a6a..af630533bc 100644 --- a/tests/s25Main/worldFixtures/WorldFixture.h +++ b/tests/s25Main/worldFixtures/WorldFixture.h @@ -97,7 +97,9 @@ struct WorldFixtureBase std::vector(numPlayers, GetPlayer()))), em(static_cast(*game->em_)), ggs(const_cast(game->ggs_)), world(game->world_) - { // Fast moving ships + { + em.setWorld(world); + // Fast moving ships ggs.setSelection(AddonId::SHIP_SPEED, 4); // Explored area stays explored. Avoids fow creation ggs.exploration = Exploration::Classic;