diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ab2c3860..20267f64b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,12 +2,16 @@ # # SPDX-License-Identifier: GPL-2.0-or-later +name: Create Release + on: push: tags: - 'v*' -name: Create Release +concurrency: + group: ${{format('release-{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true jobs: release: diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 2f634ca99..4983c4568 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -8,6 +8,10 @@ on: push: pull_request: +concurrency: + group: ${{format('staticAna-{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true + env: CC: clang-10 CXX: clang++-10 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 07b8aec12..391e2ad2a 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -8,6 +8,10 @@ on: push: pull_request: +concurrency: + group: ${{format('tests-{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true + env: BOOST_VERSION: 1.69.0 ADDITIONAL_CMAKE_FLAGS: -DRTTR_ENABLE_BENCHMARKS=ON diff --git a/external/libsiedler2 b/external/libsiedler2 index ea2047ca9..eea374481 160000 --- a/external/libsiedler2 +++ b/external/libsiedler2 @@ -1 +1 @@ -Subproject commit ea2047ca92df4c495db16e7972b75cd45105ca00 +Subproject commit eea3744814d347baaff2923e6b0572b6f9de08ae diff --git a/external/libutil b/external/libutil index 3b1abe683..423c6e343 160000 --- a/external/libutil +++ b/external/libutil @@ -1 +1 @@ -Subproject commit 3b1abe6833418a05d5bfd8f4debf6bbd27213604 +Subproject commit 423c6e343cf953e2c08aed2d93c865e2a087b2e3 diff --git a/libs/s25main/BasePlayerInfo.cpp b/libs/s25main/BasePlayerInfo.cpp index 0c16928a1..b07a967a3 100644 --- a/libs/s25main/BasePlayerInfo.cpp +++ b/libs/s25main/BasePlayerInfo.cpp @@ -24,16 +24,7 @@ BasePlayerInfo::BasePlayerInfo(Serializer& ser, bool lightData) name = ser.PopLongString(); nation = helpers::popEnum(ser); color = ser.PopUnsignedInt(); - // Temporary workaround: The random team was stored in the file but should not anymore, see PR #1331 - auto tmpTeam = ser.Pop(); - if(tmpTeam > static_cast(Team::Team4)) - tmpTeam -= 3; // Was random team 2-4 - else if(tmpTeam > helpers::MaxEnumValue_v) - throw helpers::makeOutOfRange(tmpTeam, helpers::MaxEnumValue_v); - team = Team(tmpTeam); - if(team == Team::Random) - team = Team::Team1; // Was random team 1 - // team = helpers::popEnum(ser); + team = helpers::popEnum(ser); } } diff --git a/libs/s25main/CatapultStone.cpp b/libs/s25main/CatapultStone.cpp index 3e806f8a5..3674d37e3 100644 --- a/libs/s25main/CatapultStone.cpp +++ b/libs/s25main/CatapultStone.cpp @@ -54,7 +54,7 @@ void CatapultStone::Draw(DrawPoint drawOffset) DrawPoint drawPos = destPos - drawOffset + worldSize; drawPos.x %= worldSize.x; drawPos.y %= worldSize.y; - LOADER.GetMapPlayerImage(3102 + GAMECLIENT.Interpolate(4, event))->DrawFull(drawPos); + LOADER.GetMapTexture(3102 + GAMECLIENT.Interpolate(4, event))->DrawFull(drawPos); } else { // Linear interpolieren zwischen Ausgangs- und Zielpunkt @@ -64,7 +64,7 @@ void CatapultStone::Draw(DrawPoint drawOffset) drawPos.x %= worldSize.x; drawPos.y %= worldSize.y; // Schatten auf linearer Linie zeichnen - LOADER.GetMapImageN(3101)->DrawFull(drawPos, COLOR_SHADOW); + LOADER.GetMapTexture(3101)->DrawFull(drawPos, COLOR_SHADOW); Position distance = destPos - startPos; double whole = std::sqrt(double(distance.x * distance.x + distance.y * distance.y)); @@ -80,7 +80,7 @@ void CatapultStone::Draw(DrawPoint drawOffset) // Stein auf Parabel zeichnen drawPos.y = (drawPos.y + diff) % worldSize.y; - LOADER.GetMapPlayerImage(3100)->DrawFull(drawPos); + LOADER.GetMapTexture(3100)->DrawFull(drawPos); } } diff --git a/libs/s25main/FOWObjects.cpp b/libs/s25main/FOWObjects.cpp index c775f599c..dc4b4121c 100644 --- a/libs/s25main/FOWObjects.cpp +++ b/libs/s25main/FOWObjects.cpp @@ -144,12 +144,12 @@ void fowTree::Draw(DrawPoint drawPt) const if(size == 3) { // Ausgewachsen - LOADER.GetMapImageN(200 + type * 15)->DrawFull(drawPt, FOW_DRAW_COLOR); - LOADER.GetMapImageN(350 + type * 15)->DrawFull(drawPt, COLOR_SHADOW); + LOADER.GetMapTexture(200 + type * 15)->DrawFull(drawPt, FOW_DRAW_COLOR); + LOADER.GetMapTexture(350 + type * 15)->DrawFull(drawPt, COLOR_SHADOW); } else { - LOADER.GetMapImageN(208 + type * 15 + size)->DrawFull(drawPt, FOW_DRAW_COLOR); - LOADER.GetMapImageN(358 + type * 15 + size)->DrawFull(drawPt, COLOR_SHADOW); + LOADER.GetMapTexture(208 + type * 15 + size)->DrawFull(drawPt, FOW_DRAW_COLOR); + LOADER.GetMapTexture(358 + type * 15 + size)->DrawFull(drawPt, COLOR_SHADOW); } } diff --git a/libs/s25main/Loader.cpp b/libs/s25main/Loader.cpp index 65f891e3b..b27c425a1 100644 --- a/libs/s25main/Loader.cpp +++ b/libs/s25main/Loader.cpp @@ -163,12 +163,12 @@ glArchivItem_Bitmap_Player* Loader::GetNationPlayerImage(Nation nation, unsigned return checkedCast(GetNationImageN(nation, nr)); } -glArchivItem_Bitmap* Loader::GetMapImageN(unsigned nr) +glArchivItem_Bitmap* Loader::GetMapImage(unsigned nr) { return convertChecked(map_gfx->get(nr)); } -ITexture* Loader::GetMapTexN(unsigned nr) +ITexture* Loader::GetMapTexture(unsigned nr) { return convertChecked(map_gfx->get(nr)); } @@ -343,6 +343,47 @@ void Loader::LoadDummyGUIFiles() } } +void Loader::LoadDummyMapFiles() +{ + libsiedler2::Archiv& map = files_["map_0_z"].archive; + if(!map.empty()) + return; + const auto pushRange = [&map](unsigned from, unsigned to) { + map.alloc_inc(to - map.size() + 1); + libsiedler2::PixelBufferBGRA buffer(1, 1); + for(unsigned i = from; i <= to; i++) + { + auto bmp = std::make_unique(); + bmp->create(buffer); + map.set(i, std::move(bmp)); + }; + }; + map_gfx = ↦ + + // Some ID ranges as found in map_0_z.lst + pushRange(20, 23); + pushRange(40, 46); + pushRange(50, 55); + pushRange(59, 67); + pushRange(200, 282); + pushRange(290, 334); + pushRange(350, 432); + pushRange(440, 484); + pushRange(500, 527); + + for(int j = 0; j <= 5; j++) + { + libsiedler2::Archiv& bobs = files_[ResourceId("mis" + std::to_string(j) + "bobs")].archive; + libsiedler2::PixelBufferBGRA buffer(1, 1); + for(unsigned i = 0; i <= 10; i++) + { + auto bmp = std::make_unique(); + bmp->create(buffer); + bobs.push(std::move(bmp)); + } + } +} + namespace { struct NationResourcesSource { @@ -473,17 +514,17 @@ void Loader::fillCaches() bmp.reset(); - bmp.add(GetMapImageN(ANIMALCONSTS[species].walking_id - + ANIMALCONSTS[species].animation_steps * rttr::enum_cast(dir + 3u) + ani_step)); + bmp.add(GetMapImage(ANIMALCONSTS[species].walking_id + + ANIMALCONSTS[species].animation_steps * rttr::enum_cast(dir + 3u) + ani_step)); if(ANIMALCONSTS[species].shadow_id) { if(species == Species::Duck) // Ente Sonderfall, da gibts nur einen Schatten für jede Richtung! - bmp.addShadow(GetMapImageN(ANIMALCONSTS[species].shadow_id)); + bmp.addShadow(GetMapImage(ANIMALCONSTS[species].shadow_id)); else // ansonsten immer pro Richtung einen Schatten - bmp.addShadow(GetMapImageN(ANIMALCONSTS[species].shadow_id + rttr::enum_cast(dir + 3u))); + bmp.addShadow(GetMapImage(ANIMALCONSTS[species].shadow_id + rttr::enum_cast(dir + 3u))); } stp->add(bmp); @@ -496,11 +537,11 @@ void Loader::fillCaches() if(ANIMALCONSTS[species].dead_id) { - bmp.add(GetMapImageN(ANIMALCONSTS[species].dead_id)); + bmp.add(GetMapImage(ANIMALCONSTS[species].dead_id)); if(ANIMALCONSTS[species].shadow_dead_id) { - bmp.addShadow(GetMapImageN(ANIMALCONSTS[species].shadow_dead_id)); + bmp.addShadow(GetMapImage(ANIMALCONSTS[species].shadow_dead_id)); } stp->add(bmp); @@ -593,7 +634,7 @@ void Loader::fillCaches() bob_jobs->getBody(spriteData.isFat(), imgDir, ani_step))); bmp.add(dynamic_cast( bob_jobs->getOverlay(spriteData.getBobId(Nation(nation)), spriteData.isFat(), imgDir, ani_step))); - bmp.addShadow(GetMapImageN(900 + static_cast(imgDir) * 8 + ani_step)); + bmp.addShadow(GetMapImage(900 + static_cast(imgDir) * 8 + ani_step)); stp->add(bmp); } @@ -611,7 +652,7 @@ void Loader::fillCaches() bmp.add(dynamic_cast(bob_jobs->getBody(true, imgDir, ani_step))); bmp.add(dynamic_cast(bob_jobs->getOverlay(0, true, imgDir, ani_step))); - bmp.addShadow(GetMapImageN(900 + static_cast(imgDir) * 8 + ani_step)); + bmp.addShadow(GetMapImage(900 + static_cast(imgDir) * 8 + ani_step)); stp->add(bmp); } @@ -681,10 +722,10 @@ void Loader::fillCaches() bmp.reset(); - bmp.add(static_cast(GetMapImageN(3162+ani_step))); + bmp.add(static_cast(GetMapTexture(3162+ani_step))); int a, b, c, d; - static_cast(GetMapImageN(3162+ani_step))->getVisibleArea(a, b, c, d); + static_cast(GetMapTexture(3162+ani_step))->getVisibleArea(a, b, c, d); fprintf(stderr, "%i,%i (%ix%i)\n", a, b, c, d); @@ -700,8 +741,8 @@ void Loader::fillCaches() bmp.reset(); - bmp.add(GetMapImageN(200 + type * 15 + ani_step)); - bmp.addShadow(GetMapImageN(350 + type * 15 + ani_step)); + bmp.add(GetMapImage(200 + type * 15 + ani_step)); + bmp.addShadow(GetMapImage(350 + type * 15 + ani_step)); stp->add(bmp); } @@ -716,8 +757,8 @@ void Loader::fillCaches() bmp.reset(); - bmp.add(GetMapImageN(516 + rttr::enum_cast(type) * 6 + size)); - bmp.addShadow(GetMapImageN(616 + rttr::enum_cast(type) * 6 + size)); + bmp.add(GetMapImage(516 + rttr::enum_cast(type) * 6 + size)); + bmp.addShadow(GetMapImage(616 + rttr::enum_cast(type) * 6 + size)); stp->add(bmp); } @@ -732,8 +773,8 @@ void Loader::fillCaches() bmp.reset(); - bmp.add(GetMapImageN(532 + type * 5 + size)); - bmp.addShadow(GetMapImageN(632 + type * 5 + size)); + bmp.add(GetMapImage(532 + type * 5 + size)); + bmp.addShadow(GetMapImage(632 + type * 5 + size)); stp->add(bmp); } @@ -748,8 +789,8 @@ void Loader::fillCaches() bmp.reset(); - bmp.add(GetMapImageN(2000 + rttr::enum_cast(dir + 3u) * 8 + ani_step)); - bmp.addShadow(GetMapImageN(2048 + rttr::enum_cast(dir) % 3)); + bmp.add(GetMapImage(2000 + rttr::enum_cast(dir + 3u) * 8 + ani_step)); + bmp.addShadow(GetMapImage(2048 + rttr::enum_cast(dir) % 3)); stp->add(bmp); } @@ -765,7 +806,7 @@ void Loader::fillCaches() bmp.reset(); bmp.add(GetPlayerImage("boat", rttr::enum_cast(dir + 3u) * 8 + ani_step)); - bmp.addShadow(GetMapImageN(2048 + rttr::enum_cast(dir) % 3)); + bmp.addShadow(GetMapImage(2048 + rttr::enum_cast(dir) % 3)); stp->add(bmp); } @@ -796,7 +837,7 @@ void Loader::fillCaches() bmp.add(dynamic_cast(bob_carrier->getBody(fat, imgDir, ani_step))); bmp.add( dynamic_cast(bob_carrier->getOverlay(id, fat, imgDir, ani_step))); - bmp.addShadow(GetMapImageN(900 + static_cast(imgDir) * 8 + ani_step)); + bmp.addShadow(GetMapImage(900 + static_cast(imgDir) * 8 + ani_step)); stp->add(bmp); } @@ -810,8 +851,8 @@ void Loader::fillCaches() const unsigned char color_count = 4; libsiedler2::ArchivItem_Palette* palette = GetPaletteN("pal5"); - glArchivItem_Bitmap* image = GetMapImageN(561); - glArchivItem_Bitmap* shadow = GetMapImageN(661); + auto* image = GetMapImage(561); + auto* shadow = GetMapImage(661); if((image) && (shadow) && (palette)) { diff --git a/libs/s25main/Loader.h b/libs/s25main/Loader.h index 7d434056d..fcec6e656 100644 --- a/libs/s25main/Loader.h +++ b/libs/s25main/Loader.h @@ -85,6 +85,7 @@ class Loader /// Creates archives with empty files for the GUI (for testing purposes) void LoadDummyGUIFiles(); + void LoadDummyMapFiles(); /// Load a file and save it into the loader repo bool Load(const boost::filesystem::path& path, const libsiedler2::ArchivItem_Palette* palette = nullptr); bool Load(const ResourceId& resId, const libsiedler2::ArchivItem_Palette* palette = nullptr); @@ -117,22 +118,26 @@ class Loader /// Same as GetNationImage but returns a ITexture. Note glArchivItem_Bitmap is a ITexture ITexture* GetNationTex(Nation nation, unsigned nr); glArchivItem_Bitmap_Player* GetNationPlayerImage(Nation nation, unsigned nr); - glArchivItem_Bitmap* GetMapImageN(unsigned nr); - /// Same as GetMapImageN but returns a ITexture. Note glArchivItem_Bitmap is a ITexture - ITexture* GetMapTexN(unsigned nr); + /// Return the map texture with the given number + ITexture* GetMapTexture(unsigned nr); + /// Return the more specialized map image. Note: Prefer GetMapTexture which also handles (pseudo) player bitmaps + glArchivItem_Bitmap* GetMapImage(unsigned nr); /// Get the ware symbol texture - ITexture* GetWareTex(GoodType ware) { return GetMapTexN(WARES_TEX_MAP_OFFSET + rttr::enum_cast(ware)); } + ITexture* GetWareTex(GoodType ware) { return GetMapTexture(WARES_TEX_MAP_OFFSET + rttr::enum_cast(ware)); } /// Get the ware stack texture (lying on ground) - ITexture* GetWareStackTex(GoodType ware) { return GetMapTexN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(ware)); } + ITexture* GetWareStackTex(GoodType ware) + { + return GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(ware)); + } /// Get the ware texture when carried by donky ITexture* GetWareDonkeyTex(GoodType ware) { - return GetMapTexN(WARES_DONKEY_TEX_MAP_OFFSET + rttr::enum_cast(ware)); + return GetMapTexture(WARES_DONKEY_TEX_MAP_OFFSET + rttr::enum_cast(ware)); } /// Get job symbol texture ITexture* GetJobTex(Job job) { - return (job == Job::CharBurner) ? GetTextureN("io_new", 5) : GetMapTexN(2300 + rttr::enum_cast(job)); + return (job == Job::CharBurner) ? GetTextureN("io_new", 5) : GetMapTexture(2300 + rttr::enum_cast(job)); } glArchivItem_Bitmap_Player* GetMapPlayerImage(unsigned nr); diff --git a/libs/s25main/SavedFile.cpp b/libs/s25main/SavedFile.cpp index 3cae00251..870931c55 100644 --- a/libs/s25main/SavedFile.cpp +++ b/libs/s25main/SavedFile.cpp @@ -5,6 +5,7 @@ #include "SavedFile.h" #include "BasePlayerInfo.h" #include "RTTR_Version.h" +#include "enum_cast.hpp" #include "libendian/ConvertEndianess.h" #include "s25util/BinaryFile.h" #include "s25util/Serializer.h" @@ -131,7 +132,15 @@ void SavedFile::ReadPlayerData(BinaryFile& file) const unsigned playerCt = ser.PopUnsignedChar(); players.reserve(playerCt); for(unsigned i = 0; i < playerCt; i++) - AddPlayer(BasePlayerInfo(ser, true)); + { + BasePlayerInfo player(ser, true); + // Temporary workaround: The random team was stored in the file but should not anymore, see PR #1331 + if(player.team > Team::Team4) + player.team = Team(rttr::enum_cast(player.team) - 3); // Was random team 2-4 + else if(player.team == Team::Random) + player.team = Team::Team1; // Was random team 1 + AddPlayer(player); + } } /** diff --git a/libs/s25main/ai/aijh/AIConstruction.cpp b/libs/s25main/ai/aijh/AIConstruction.cpp index 035bf3c5a..358f286bb 100644 --- a/libs/s25main/ai/aijh/AIConstruction.cpp +++ b/libs/s25main/ai/aijh/AIConstruction.cpp @@ -468,8 +468,7 @@ helpers::OptionalEnum AIConstruction::ChooseMilitaryBuilding(const if(((rand() % 3) == 0 || inventory.people[Job::Private] < 15) && (inventory.goods[GoodType::Stones] > 6 || bldPlanner.GetNumBuildings(BuildingType::Quarry) > 0)) bld = BuildingType::Guardhouse; - if(aijh.getAIInterface().isHarborPosClose(pt, 19) && rand() % 10 != 0 - && aijh.ggs.getSelection(AddonId::SEA_ATTACK) != 2) + if(aijh.getAIInterface().isHarborPosClose(pt, 19) && rand() % 10 != 0 && aijh.ggs.isEnabled(AddonId::SEA_ATTACK)) { if(aii.CanBuildBuildingtype(BuildingType::Watchtower)) return BuildingType::Watchtower; diff --git a/libs/s25main/ai/aijh/AIPlayerJH.cpp b/libs/s25main/ai/aijh/AIPlayerJH.cpp index 4c7112dae..19c8f9ab7 100644 --- a/libs/s25main/ai/aijh/AIPlayerJH.cpp +++ b/libs/s25main/ai/aijh/AIPlayerJH.cpp @@ -268,7 +268,7 @@ void AIPlayerJH::RunGF(const unsigned gf, bool gfisnwf) if((gf + 41 + playerId * 17) % attack_interval == 0) { - if(ggs.getSelection(AddonId::SEA_ATTACK) < 2) // not deactivated by addon? -> go ahead + if(ggs.isEnabled(AddonId::SEA_ATTACK)) TrySeaAttack(); } @@ -2438,7 +2438,7 @@ void AIPlayerJH::AdjustSettings() 8 : 0; milSettings[6] = - ggs.getSelection(AddonId::SEA_ATTACK) == 2 ? 0 : 8; // harbor flag: no sea attacks?->no soldiers else 50% to 100% + ggs.isEnabled(AddonId::SEA_ATTACK) ? 8 : 0; // harbor flag: no sea attacks?->no soldiers else 50% to 100% milSettings[5] = CalcMilSettings(); // inland 1bar min 50% max 100% depending on how many soldiers are available milSettings[7] = 8; // front: 100% if(player.GetMilitarySetting(5) != milSettings[5] || player.GetMilitarySetting(6) != milSettings[6] @@ -2465,7 +2465,7 @@ unsigned AIPlayerJH::CalcMilSettings() for(const nobMilitary* milBld : militaryBuildings) { if(milBld->GetFrontierDistance() == FrontierDistance::Near - || (milBld->GetFrontierDistance() == FrontierDistance::Harbor && ggs.getSelection(AddonId::SEA_ATTACK) != 2) + || milBld->GetFrontierDistance() == FrontierDistance::Harbor || (milBld->GetFrontierDistance() == FrontierDistance::Far && (militaryBuildings.size() < (unsigned)count + numShouldStayConnected || count == uun))) // front or connected interior diff --git a/libs/s25main/buildings/noBuildingSite.cpp b/libs/s25main/buildings/noBuildingSite.cpp index 54a107459..9f6413ab4 100644 --- a/libs/s25main/buildings/noBuildingSite.cpp +++ b/libs/s25main/buildings/noBuildingSite.cpp @@ -192,11 +192,11 @@ void noBuildingSite::Draw(DrawPoint drawPt) // Bretter DrawPoint doorPos = drawPt + DrawPoint(GetDoorPointX(), GetDoorPointY()); for(unsigned char i = 0; i < boards; ++i) - LOADER.GetMapImageN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Boards)) + LOADER.GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Boards)) ->DrawFull(doorPos - DrawPoint(5, 10 + i * 4)); // Steine for(unsigned char i = 0; i < stones; ++i) - LOADER.GetMapImageN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Stones)) + LOADER.GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Stones)) ->DrawFull(doorPos + DrawPoint(8, -12 - i * 4)); // bis dahin gebautes Haus zeichnen diff --git a/libs/s25main/buildings/nobHQ.cpp b/libs/s25main/buildings/nobHQ.cpp index fa935d683..c02d5a3ea 100644 --- a/libs/s25main/buildings/nobHQ.cpp +++ b/libs/s25main/buildings/nobHQ.cpp @@ -355,7 +355,7 @@ void nobHQ::Draw(DrawPoint drawPt) glArchivItem_Bitmap_Player* bitmap = LOADER.GetMapPlayerImage(3162 + GAMECLIENT.GetGlobalAnimation(8, 80, 40, GetX() * GetY() * i)); if(bitmap) - bitmap->DrawFull(flagsPos + DrawPoint(0, (i - 1) * 3), COLOR_WHITE, world->GetPlayer(player).color); + bitmap->drawForPlayer(flagsPos + DrawPoint(0, (i - 1) * 3), world->GetPlayer(player).color); } } } diff --git a/libs/s25main/buildings/nobHarborBuilding.cpp b/libs/s25main/buildings/nobHarborBuilding.cpp index e5bb02df8..9a4669dd6 100644 --- a/libs/s25main/buildings/nobHarborBuilding.cpp +++ b/libs/s25main/buildings/nobHarborBuilding.cpp @@ -225,14 +225,14 @@ void nobHarborBuilding::Draw(DrawPoint drawPt) ->DrawFull(drawPt + FIRE_POS[nation]); } else if(nation == Nation::Africans || nation == Nation::Vikings) { - LOADER.GetMapPlayerImage(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY())) + LOADER.GetMapTexture(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY())) ->DrawFull(drawPt + FIRE_POS[nation]); } if(nation == Nation::Romans) { // Zusätzliches Feuer - LOADER.GetMapPlayerImage(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY())) + LOADER.GetMapTexture(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY())) ->DrawFull(drawPt + EXTRAFIRE_POS[nation]); } @@ -244,12 +244,12 @@ void nobHarborBuilding::Draw(DrawPoint drawPt) // Bretter DrawPoint boardsPos = drawPt + BOARDS_POS[nation]; for(unsigned char i = 0; i < expedition.boards; ++i) - LOADER.GetMapImageN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Boards)) + LOADER.GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Boards)) ->DrawFull(boardsPos - DrawPoint(0, i * 4)); DrawPoint stonesPos = drawPt + STONES_POS[nation]; // Steine for(unsigned char i = 0; i < expedition.stones; ++i) - LOADER.GetMapImageN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Stones)) + LOADER.GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(GoodType::Stones)) ->DrawFull(stonesPos - DrawPoint(0, i * 4)); // Und den Bauarbeiter, falls er schon da ist diff --git a/libs/s25main/buildings/nobMilitary.cpp b/libs/s25main/buildings/nobMilitary.cpp index fa54e68b8..bac984d39 100644 --- a/libs/s25main/buildings/nobMilitary.cpp +++ b/libs/s25main/buildings/nobMilitary.cpp @@ -173,13 +173,13 @@ void nobMilitary::Draw(DrawPoint drawPt) { const unsigned flagTexture = 3162 + GAMECLIENT.GetGlobalAnimation(8, 2, 1, pos.x * pos.y * i); LOADER.GetMapPlayerImage(flagTexture) - ->DrawFull(drawPt + TROOPS_FLAG_OFFSET[nation][size] + DrawPoint(0, i * 3), COLOR_WHITE, - world->GetPlayer(player).color); + ->drawForPlayer(drawPt + TROOPS_FLAG_OFFSET[nation][size] + DrawPoint(0, i * 3), + world->GetPlayer(player).color); } // Die Fahne, die anzeigt wie weit das Gebäude von der Grenze entfernt ist, zeichnen FrontierDistance frontier_distance_tmp = frontier_distance; - glArchivItem_Bitmap_Player* bitmap = nullptr; + ITexture* bitmap = nullptr; unsigned animationFrame = GAMECLIENT.GetGlobalAnimation(4, 1, 1, pos.x * pos.y * GetObjId()); if(new_built) { @@ -187,19 +187,19 @@ void nobMilitary::Draw(DrawPoint drawPt) } else if(frontier_distance_tmp == FrontierDistance::Harbor) { // todo Hafenflagge - bitmap = LOADER.GetPlayerImage("map_new", 3150 + animationFrame); + bitmap = LOADER.GetTextureN("map_new", 3150 + animationFrame); } else { if(frontier_distance_tmp == FrontierDistance::Near) frontier_distance_tmp = FrontierDistance::Harbor; - bitmap = LOADER.GetMapPlayerImage(3150 + rttr::enum_cast(frontier_distance_tmp) * 4 + animationFrame); + bitmap = LOADER.GetMapTexture(3150 + rttr::enum_cast(frontier_distance_tmp) * 4 + animationFrame); } if(bitmap) bitmap->DrawFull(drawPt + BORDER_FLAG_OFFSET[nation][size]); // Wenn Goldzufuhr gestoppt ist, Schild außen am Gebäude zeichnen zeichnen if(coinsDisabledVirtual) - LOADER.GetMapImageN(46)->DrawFull(drawPt + BUILDING_SIGN_CONSTS[nation][bldType_]); + LOADER.GetMapTexture(46)->DrawFull(drawPt + BUILDING_SIGN_CONSTS[nation][bldType_]); } void nobMilitary::HandleEvent(const unsigned id) @@ -360,7 +360,8 @@ void nobMilitary::LookForEnemyBuildings(const nobBaseMilitary* const exception) } } // check for harbor points - if(frontier_distance <= FrontierDistance::Mid && world->CalcDistanceToNearestHarbor(pos) < SEAATTACK_DISTANCE + 2) + if(frontier_distance <= FrontierDistance::Mid && world->GetGGS().isEnabled(AddonId::SEA_ATTACK) + && world->CalcDistanceToNearestHarbor(pos) < SEAATTACK_DISTANCE + 2) frontier_distance = FrontierDistance::Harbor; // send troops diff --git a/libs/s25main/buildings/nobUsual.cpp b/libs/s25main/buildings/nobUsual.cpp index 1468b586b..2ccdd2a55 100644 --- a/libs/s25main/buildings/nobUsual.cpp +++ b/libs/s25main/buildings/nobUsual.cpp @@ -119,7 +119,7 @@ void nobUsual::Draw(DrawPoint drawPt) // Wenn Produktion gestoppt ist, Schild außen am Gebäude zeichnen zeichnen if(disable_production_virtual) - LOADER.GetMapImageN(46)->DrawFull(drawPt + BUILDING_SIGN_CONSTS[nation][bldType_]); + LOADER.GetMapTexture(46)->DrawFull(drawPt + BUILDING_SIGN_CONSTS[nation][bldType_]); // Rauch zeichnen @@ -128,8 +128,8 @@ void nobUsual::Draw(DrawPoint drawPt) { // Dann Qualm zeichnen (damit Qualm nicht synchron ist, x- und y- Koordinate als Unterscheidung LOADER - .GetMapImageN(692 + BUILDING_SMOKE_CONSTS[nation][bldType_].type * 8 - + GAMECLIENT.GetGlobalAnimation(8, 5, 2, (GetX() + GetY()) * 100)) + .GetMapTexture(692 + BUILDING_SMOKE_CONSTS[nation][bldType_].type * 8 + + GAMECLIENT.GetGlobalAnimation(8, 5, 2, (GetX() + GetY()) * 100)) ->DrawFull(drawPt + BUILDING_SMOKE_CONSTS[nation][bldType_].offset, 0x99EEEEEE); } @@ -169,7 +169,7 @@ void nobUsual::Draw(DrawPoint drawPt) { unsigned animationFrame = DONKEY_ANIMATION[GAMECLIENT.GetGlobalAnimation( DONKEY_ANIMATION.size(), 5, 2, GetX() * (player + 2) + GetY() * i)]; - LOADER.GetMapImageN(2180 + animationFrame)->DrawFull(drawPt + DONKEY_OFFSETS[nation][i]); + LOADER.GetMapTexture(2180 + animationFrame)->DrawFull(drawPt + DONKEY_OFFSETS[nation][i]); } } // Bei Katapulthaus Katapult oben auf dem Dach zeichnen, falls er nicht "arbeitet" @@ -192,8 +192,8 @@ void nobUsual::Draw(DrawPoint drawPt) }}; /// Großes Schwein zeichnen - LOADER.GetMapImageN(2160)->DrawFull(drawPt + PIG_POSITIONS[nation][0], COLOR_SHADOW); - LOADER.GetMapImageN(2100 + GAMECLIENT.GetGlobalAnimation(12, 3, 1, GetX() + GetY() + GetObjId())) + LOADER.GetMapTexture(2160)->DrawFull(drawPt + PIG_POSITIONS[nation][0], COLOR_SHADOW); + LOADER.GetMapTexture(2100 + GAMECLIENT.GetGlobalAnimation(12, 3, 1, GetX() + GetY() + GetObjId())) ->DrawFull(drawPt + PIG_POSITIONS[nation][0]); // Die 4 kleinen Schweinchen, je nach Produktivität @@ -206,8 +206,8 @@ void nobUsual::Draw(DrawPoint drawPt) 2, 0, 0, 2, 2, 0, 1, 0, 3, 1, 2, 0, 1, 2, 2, 0, 0, 0, 3, 0, 2, 0, 3, 0, 3, 0, 1, 1, 0, 3, 0}; const unsigned short animpos = GAMECLIENT.GetGlobalAnimation(63 * 12, 63 * 4 - i * 5, 1, 183 * i + GetX() * GetObjId() + GetY() * i); - LOADER.GetMapImageN(2160)->DrawFull(drawPt + PIG_POSITIONS[nation][i], COLOR_SHADOW); - LOADER.GetMapImageN(2112 + smallpig_animations[animpos / 12] * 12 + animpos % 12) + LOADER.GetMapTexture(2160)->DrawFull(drawPt + PIG_POSITIONS[nation][i], COLOR_SHADOW); + LOADER.GetMapTexture(2112 + smallpig_animations[animpos / 12] * 12 + animpos % 12) ->DrawFull(drawPt + PIG_POSITIONS[nation][i]); } @@ -226,7 +226,7 @@ void nobUsual::Draw(DrawPoint drawPt) case BuildingType::GoldMine: offset = NUBIAN_MINE_FIRE[3]; break; default: RTTR_Assert_Msg(false, "Not a mine"); } - LOADER.GetMapPlayerImage(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY())) + LOADER.GetMapTexture(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY())) ->DrawFull(drawPt + offset); } } diff --git a/libs/s25main/controls/ctrlIngameMinimap.cpp b/libs/s25main/controls/ctrlIngameMinimap.cpp index 240e6fe1c..3ab386c94 100644 --- a/libs/s25main/controls/ctrlIngameMinimap.cpp +++ b/libs/s25main/controls/ctrlIngameMinimap.cpp @@ -30,7 +30,7 @@ void ctrlIngameMinimap::Draw_() DrawPoint middle_corrected(MakeMapPoint(middlePt, minimap.GetMapSize())); // Scroll-Auswahl-Bild holen - glArchivItem_Bitmap* image = LOADER.GetMapImageN(23); + glArchivItem_Bitmap* image = LOADER.GetMapImage(23); // Position (relativ zum angezeigten Anfang der Karte) berechnen DrawPoint pos = middle_corrected * DrawPoint(GetCurMapSize()) / DrawPoint(minimap.GetMapSize()) + DrawPoint(2, 2); diff --git a/libs/s25main/figures/noFigure.cpp b/libs/s25main/figures/noFigure.cpp index 8a026ce16..8abba1486 100644 --- a/libs/s25main/figures/noFigure.cpp +++ b/libs/s25main/figures/noFigure.cpp @@ -236,7 +236,7 @@ void noFigure::StartWalking(const Direction dir) void noFigure::DrawShadow(DrawPoint drawPt, const unsigned char anistep, Direction dir) { - glArchivItem_Bitmap* bitmap = LOADER.GetMapImageN(900 + rttr::enum_cast(dir + 3u) * 8 + anistep); + auto* bitmap = LOADER.GetMapTexture(900 + rttr::enum_cast(dir + 3u) * 8 + anistep); if(bitmap) bitmap->DrawFull(drawPt, COLOR_SHADOW); } @@ -793,9 +793,9 @@ void noFigure::DrawWalking(DrawPoint drawPt) drawPt = InterpolateWalkDrawPos(drawPt); // Esel - LOADER.GetMapImageN(2000 + rttr::enum_cast(GetCurMoveDir() + 3u) * 8 + ani_step)->DrawFull(drawPt); + LOADER.GetMapTexture(2000 + rttr::enum_cast(GetCurMoveDir() + 3u) * 8 + ani_step)->DrawFull(drawPt); // Schatten des Esels - LOADER.GetMapImageN(2048 + rttr::enum_cast(GetCurMoveDir()) % 3)->DrawFull(drawPt, COLOR_SHADOW); + LOADER.GetMapTexture(2048 + rttr::enum_cast(GetCurMoveDir()) % 3)->DrawFull(drawPt, COLOR_SHADOW); } break; case Job::CharBurner: DrawWalking(drawPt, "charburner_bobs", 53); break; diff --git a/libs/s25main/gameTypes/AIInfo.h b/libs/s25main/gameTypes/AIInfo.h index 322f0686e..f1474d0d6 100644 --- a/libs/s25main/gameTypes/AIInfo.h +++ b/libs/s25main/gameTypes/AIInfo.h @@ -36,5 +36,7 @@ struct Info Info(Type t = Type::Dummy, Level l = Level::Easy) : type(t), level(l) {} Info(Serializer& ser); void serialize(Serializer& ser) const; + + bool operator==(const Info& rhs) const { return type == rhs.type && level == rhs.level; } }; } // namespace AI diff --git a/libs/s25main/gameTypes/GameTypesOutput.h b/libs/s25main/gameTypes/GameTypesOutput.h index 1a9c7d40c..598b549fc 100644 --- a/libs/s25main/gameTypes/GameTypesOutput.h +++ b/libs/s25main/gameTypes/GameTypesOutput.h @@ -17,6 +17,7 @@ #include "PactTypes.h" #include "PlayerState.h" #include "Resource.h" +#include "ServerType.h" #include "gameTypes/BuildingQuality.h" #include "gameTypes/Direction.h" #include "gameTypes/FoWNode.h" @@ -65,6 +66,7 @@ RTTR_ENUM_OUTPUT(Species, PolarBear, RabbitWhite, RabbitGrey, Fox, Stag, Deer, D RTTR_ENUM_OUTPUT(StartWares, VLow, Low, Normal, ALot) RTTR_ENUM_OUTPUT(Visibility, Invisible, FogOfWar, Visible) RTTR_ENUM_OUTPUT(Team, None, Random, Team1, Team2, Team3, Team4, Random1To2, Random1To3, Random1To4) +RTTR_ENUM_OUTPUT(ServerType, Lobby, Direct, Local, LAN) namespace AI { RTTR_ENUM_OUTPUT(Type, Dummy, Default) diff --git a/libs/s25main/gameTypes/ServerType.h b/libs/s25main/gameTypes/ServerType.h index c2463c6f7..1af958080 100644 --- a/libs/s25main/gameTypes/ServerType.h +++ b/libs/s25main/gameTypes/ServerType.h @@ -5,10 +5,14 @@ #pragma once // Servertypen -enum class ServerType +enum class ServerType : uint16_t { Lobby, Direct, Local, LAN }; +constexpr auto maxEnumValue(ServerType) +{ + return ServerType::LAN; +} \ No newline at end of file diff --git a/libs/s25main/ingameWindows/iwAIDebug.cpp b/libs/s25main/ingameWindows/iwAIDebug.cpp index 54bb86b9d..4b0b26038 100644 --- a/libs/s25main/ingameWindows/iwAIDebug.cpp +++ b/libs/s25main/ingameWindows/iwAIDebug.cpp @@ -31,8 +31,8 @@ enum class iwAIDebug::DebugPrinter : public IDrawNodeCallback { - helpers::EnumArray bqImgs; - std::array ticks; + helpers::EnumArray bqImgs; + std::array ticks; glFont& font; public: @@ -41,10 +41,10 @@ class iwAIDebug::DebugPrinter : public IDrawNodeCallback // Cache images for(const auto i : helpers::enumRange()) { - bqImgs[i] = LOADER.GetMapImageN(49 + rttr::enum_cast(i)); + bqImgs[i] = LOADER.GetMapTexture(49 + rttr::enum_cast(i)); } - ticks[0] = LOADER.GetImageN("io", 40); - ticks[1] = LOADER.GetImageN("io", 32); + ticks[0] = LOADER.GetTextureN("io", 40); + ticks[1] = LOADER.GetTextureN("io", 32); bqImgs[BuildingQuality::Nothing] = nullptr; bqImgs[BuildingQuality::Harbor] = ticks[0]; // Invalid marker } @@ -58,7 +58,7 @@ class iwAIDebug::DebugPrinter : public IDrawNodeCallback return; if(overlay == 1) { - glArchivItem_Bitmap* img = bqImgs[ai->GetAINode(pt).bq]; + auto* img = bqImgs[ai->GetAINode(pt).bq]; if(img) img->DrawFull(curPos); } else if(overlay == 2) diff --git a/libs/s25main/ingameWindows/iwBuilding.cpp b/libs/s25main/ingameWindows/iwBuilding.cpp index 4f14fae6b..5619bf8f1 100644 --- a/libs/s25main/ingameWindows/iwBuilding.cpp +++ b/libs/s25main/ingameWindows/iwBuilding.cpp @@ -34,7 +34,7 @@ iwBuilding::iwBuilding(GameWorldView& gwv, GameCommandFactory& gcFactory, nobUsu gwv(gwv), gcFactory(gcFactory), building(building) { // Arbeitersymbol - AddImage(0, DrawPoint(28, 39), LOADER.GetMapImageN(2298)); + AddImage(0, DrawPoint(28, 39), LOADER.GetMapTexture(2298)); if(const auto job = BLD_WORK_DESC[building->GetBuildingType()].job) AddImage(13, DrawPoint(28, 39), LOADER.GetJobTex(*job)); @@ -46,7 +46,7 @@ iwBuilding::iwBuilding(GameWorldView& gwv, GameCommandFactory& gcFactory, nobUsu const auto producedWare = BLD_WORK_DESC[building->GetBuildingType()].producedWare; if(producedWare && producedWare != GoodType::Nothing) { - AddImage(2, DrawPoint(196, 39), LOADER.GetMapImageN(2298)); + AddImage(2, DrawPoint(196, 39), LOADER.GetMapTexture(2298)); AddImage(3, DrawPoint(196, 39), LOADER.GetWareTex(*producedWare)); } diff --git a/libs/s25main/ingameWindows/iwEconomicProgress.cpp b/libs/s25main/ingameWindows/iwEconomicProgress.cpp index e6c50c3e5..c74f804b7 100644 --- a/libs/s25main/ingameWindows/iwEconomicProgress.cpp +++ b/libs/s25main/ingameWindows/iwEconomicProgress.cpp @@ -72,7 +72,7 @@ iwEconomicProgress::iwEconomicProgress(const GameWorldViewer& gwv) { GoodType good = goodsToCollect[i]; - AddImage(100 + i, curBoxPos + wareIconSize / 2, LOADER.GetMapImageN(2298), _(WARE_NAMES[good])); + AddImage(100 + i, curBoxPos + wareIconSize / 2, LOADER.GetMapTexture(2298), _(WARE_NAMES[good])); const DrawPoint warePos = curBoxPos + wareIconSize / 2; AddImage(200 + i, warePos, LOADER.GetWareTex(good)); diff --git a/libs/s25main/ingameWindows/iwHQ.cpp b/libs/s25main/ingameWindows/iwHQ.cpp index 827d4a0f0..9a3d8c7d0 100644 --- a/libs/s25main/ingameWindows/iwHQ.cpp +++ b/libs/s25main/ingameWindows/iwHQ.cpp @@ -27,9 +27,9 @@ iwHQ::iwHQ(GameWorldView& gwv, GameCommandFactory& gcFactory, nobBaseWarehouse* for(unsigned i = 0; i < 5; ++i) { // Bildhintergrund - reserve.AddImage(1 + i, DrawPoint(34, 124 + Y_DISTANCE * i), LOADER.GetMapImageN(2298)); + reserve.AddImage(1 + i, DrawPoint(34, 124 + Y_DISTANCE * i), LOADER.GetMapTexture(2298)); // Rang-Bild - reserve.AddImage(6 + i, DrawPoint(34, 124 + Y_DISTANCE * i), LOADER.GetMapImageN(2321 + i)); + reserve.AddImage(6 + i, DrawPoint(34, 124 + Y_DISTANCE * i), LOADER.GetMapTexture(2321 + i)); // Minus-Button reserve.AddImageButton(11 + i, DrawPoint(54, 112 + Y_DISTANCE * i), Extent(24, 24), TextureColor::Red1, LOADER.GetImageN("io", 139), _("Less")); diff --git a/libs/s25main/ingameWindows/iwMilitaryBuilding.cpp b/libs/s25main/ingameWindows/iwMilitaryBuilding.cpp index 2f8839779..790df14ed 100644 --- a/libs/s25main/ingameWindows/iwMilitaryBuilding.cpp +++ b/libs/s25main/ingameWindows/iwMilitaryBuilding.cpp @@ -33,11 +33,11 @@ iwMilitaryBuilding::iwMilitaryBuilding(GameWorldView& gwv, GameCommandFactory& g gwv(gwv), gcFactory(gcFactory), building(building) { // Schwert - AddImage(0, DrawPoint(28, 39), LOADER.GetMapImageN(2298)); + AddImage(0, DrawPoint(28, 39), LOADER.GetMapTexture(2298)); AddImage(1, DrawPoint(28, 39), LOADER.GetWareTex(GoodType::Sword)); // Schild - AddImage(2, DrawPoint(196, 39), LOADER.GetMapImageN(2298)); + AddImage(2, DrawPoint(196, 39), LOADER.GetMapTexture(2298)); AddImage(3, DrawPoint(196, 39), LOADER.GetWareTex(GoodType::ShieldRomans)); // Hilfe @@ -75,7 +75,7 @@ void iwMilitaryBuilding::Draw_() goldPos += DrawPoint(12, 12); for(unsigned short i = 0; i < maxCoinCt; ++i) { - LOADER.GetMapImageN(2278)->DrawFull(goldPos, (i >= building->GetNumCoins() ? 0xFFA0A0A0 : 0xFFFFFFFF)); + LOADER.GetMapTexture(2278)->DrawFull(goldPos, (i >= building->GetNumCoins() ? 0xFFA0A0A0 : 0xFFFFFFFF)); goldPos.x += 22; } @@ -102,7 +102,7 @@ void iwMilitaryBuilding::Draw_() DrawPoint curTroopsPos = troopsPos + DrawPoint(12, 12); for(const auto* soldier : soldiers) { - LOADER.GetMapImageN(2321 + soldier->GetRank())->DrawFull(curTroopsPos); + LOADER.GetMapTexture(2321 + soldier->GetRank())->DrawFull(curTroopsPos); curTroopsPos.x += 22; } diff --git a/libs/s25main/ingameWindows/iwObservate.cpp b/libs/s25main/ingameWindows/iwObservate.cpp index 63699e62f..ccbc7df8c 100644 --- a/libs/s25main/ingameWindows/iwObservate.cpp +++ b/libs/s25main/ingameWindows/iwObservate.cpp @@ -173,7 +173,7 @@ void iwObservate::Draw_() view->Draw(road, parentView.GetSelectedPt(), false); // Draw indicator for center point if(!followMovableId) - LOADER.GetMapImageN(23)->DrawFull(view->GetPos() + view->GetSize() / 2u); + LOADER.GetMapTexture(23)->DrawFull(view->GetPos() + view->GetSize() / 2u); } return IngameWindow::Draw_(); diff --git a/libs/s25main/ingameWindows/iwShip.cpp b/libs/s25main/ingameWindows/iwShip.cpp index c9d99e935..d580807ed 100644 --- a/libs/s25main/ingameWindows/iwShip.cpp +++ b/libs/s25main/ingameWindows/iwShip.cpp @@ -248,7 +248,7 @@ void iwShip::DrawCargo() orderedFigures[job]--; if(job == Job::PackDonkey) - LOADER.GetMapImageN(2016)->DrawFull(drawPt); + LOADER.GetMapTexture(2016)->DrawFull(drawPt); else if(job == Job::BoatCarrier) LOADER.GetBob("carrier")->Draw(rttr::enum_cast(GoodType::Boat), libsiedler2::ImgDir::SW, false, 0, drawPt, owner.color); @@ -279,7 +279,7 @@ void iwShip::DrawCargo() const auto draw_id = convertShieldToNation(ware, owner.nation); - LOADER.GetMapImageN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(draw_id))->DrawFull(drawPt); + LOADER.GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(draw_id))->DrawFull(drawPt); drawPt.x += xStep; lineCounter++; } diff --git a/libs/s25main/ingameWindows/iwTransport.cpp b/libs/s25main/ingameWindows/iwTransport.cpp index 31f57273f..2de51a2a0 100644 --- a/libs/s25main/ingameWindows/iwTransport.cpp +++ b/libs/s25main/ingameWindows/iwTransport.cpp @@ -38,7 +38,7 @@ iwTransport::iwTransport(const GameWorldViewer& gwv, GameCommandFactory& gcFacto // Buttons der einzelnen Waren anlegen ctrlOptionGroup* group = AddOptionGroup(6, GroupSelectType::Illuminate); - auto getGoodTex = [](GoodType good) { return LOADER.GetMapTexN(WARES_TEX_MAP_OFFSET + rttr::enum_cast(good)); }; + auto getGoodTex = [](GoodType good) { return LOADER.GetMapTexture(WARES_TEX_MAP_OFFSET + rttr::enum_cast(good)); }; buttonData = {{{getGoodTex(GoodType::Coins), WARE_NAMES[GoodType::Coins]}, {LOADER.GetTextureN("io", 111), gettext_noop("Weapons")}, {getGoodTex(GoodType::Beer), WARE_NAMES[GoodType::Beer]}, diff --git a/libs/s25main/ingameWindows/iwWares.cpp b/libs/s25main/ingameWindows/iwWares.cpp index 861f70d1f..b81611c01 100644 --- a/libs/s25main/ingameWindows/iwWares.cpp +++ b/libs/s25main/ingameWindows/iwWares.cpp @@ -27,14 +27,14 @@ static void addElement(ctrlGroup& page, const glFont* font, const DrawPoint btPo if(allow_outhousing) { ctrlButton* b = - page.AddImageButton(100 + idOffset, btPos, btSize, TextureColor::Grey, LOADER.GetMapImageN(2298), name); + page.AddImageButton(100 + idOffset, btPos, btSize, TextureColor::Grey, LOADER.GetMapTexture(2298), name); b->SetBorder(false); } else - page.AddImage(100 + idOffset, btPos + btSize / 2, LOADER.GetMapImageN(2298), name); + page.AddImage(100 + idOffset, btPos + btSize / 2, LOADER.GetMapTexture(2298), name); // Background image for the amount const DrawPoint bgCtPos = btPos + DrawPoint(btSize.x / 2, 32); - page.AddImage(200 + idOffset, bgCtPos, LOADER.GetMapImageN(2299)); + page.AddImage(200 + idOffset, bgCtPos, LOADER.GetMapTexture(2299)); // The actual image for the element const DrawPoint warePos = btPos + btSize / 2; diff --git a/libs/s25main/lua/LuaWorld.cpp b/libs/s25main/lua/LuaWorld.cpp index 86a358995..4f74e4917 100644 --- a/libs/s25main/lua/LuaWorld.cpp +++ b/libs/s25main/lua/LuaWorld.cpp @@ -36,8 +36,21 @@ void LuaWorld::Register(kaguya::State& state) .addFunction("AddAnimal", &LuaWorld::AddAnimal)); } +static bool isValidObject(unsigned file, unsigned id) +{ + try + { + return noStaticObject::getTextures(file, id).bmp != nullptr; + } catch(const std::runtime_error&) + { + return false; + } +} + bool LuaWorld::AddEnvObject(int x, int y, unsigned id, unsigned file /* = 0xFFFF */) { + lua::assertTrue(isValidObject(file, id), "Invalid object (file/id)"); + MapPoint pt = gw.MakeMapPoint(Position(x, y)); noBase* obj = gw.GetNode(pt).obj; if(obj) @@ -57,6 +70,7 @@ bool LuaWorld::AddEnvObject(int x, int y, unsigned id, unsigned file /* = 0xFFFF bool LuaWorld::AddStaticObject(int x, int y, unsigned id, unsigned file /* = 0xFFFF */, unsigned size /* = 1 */) { lua::assertTrue(size <= 2, "Invalid size"); + lua::assertTrue(isValidObject(file, id), "Invalid object (file/id)"); MapPoint pt = gw.MakeMapPoint(Position(x, y)); noBase* obj = gw.GetNode(pt).obj; diff --git a/libs/s25main/network/GameMessages.h b/libs/s25main/network/GameMessages.h index 4a62bf6b1..40d9b69ae 100644 --- a/libs/s25main/network/GameMessages.h +++ b/libs/s25main/network/GameMessages.h @@ -74,14 +74,14 @@ class GameMessage_Server_Type : public GameMessage void Serialize(Serializer& ser) const override { GameMessage::Serialize(ser); - ser.PushUnsignedShort(static_cast(type)); + helpers::pushEnum(ser, type); ser.PushLongString(revision); } void Deserialize(Serializer& ser) override { GameMessage::Deserialize(ser); - type = static_cast(ser.PopUnsignedShort()); + type = helpers::popEnum(ser); revision = ser.PopLongString(); } diff --git a/libs/s25main/nodeObjs/noCharburnerPile.cpp b/libs/s25main/nodeObjs/noCharburnerPile.cpp index d7405a3f2..22a09b699 100644 --- a/libs/s25main/nodeObjs/noCharburnerPile.cpp +++ b/libs/s25main/nodeObjs/noCharburnerPile.cpp @@ -94,11 +94,11 @@ void noCharburnerPile::Draw(DrawPoint drawPt) // Dann Qualm zeichnen unsigned globalAnimation = GAMECLIENT.GetGlobalAnimation(8, 5, 2, (this->pos.x + this->pos.y) * 100); - LOADER.GetMapImageN(692 + 1 * 8 + globalAnimation) + LOADER.GetMapTexture(692 + 1 * 8 + globalAnimation) ->DrawFull(drawPt + DrawPoint(21, -11), 0x99EEEEEE); //-V525 - LOADER.GetMapImageN(692 + 2 * 8 + globalAnimation)->DrawFull(drawPt - DrawPoint(2, 06), 0x99EEEEEE); - LOADER.GetMapImageN(692 + 1 * 8 + globalAnimation)->DrawFull(drawPt - DrawPoint(25, 11), 0x99EEEEEE); - LOADER.GetMapImageN(692 + 3 * 8 + globalAnimation)->DrawFull(drawPt - DrawPoint(2, 35), 0x99EEEEEE); + LOADER.GetMapTexture(692 + 2 * 8 + globalAnimation)->DrawFull(drawPt - DrawPoint(2, 06), 0x99EEEEEE); + LOADER.GetMapTexture(692 + 1 * 8 + globalAnimation)->DrawFull(drawPt - DrawPoint(25, 11), 0x99EEEEEE); + LOADER.GetMapTexture(692 + 3 * 8 + globalAnimation)->DrawFull(drawPt - DrawPoint(2, 35), 0x99EEEEEE); } return; case State::RemoveCover: diff --git a/libs/s25main/nodeObjs/noDisappearingMapEnvObject.cpp b/libs/s25main/nodeObjs/noDisappearingMapEnvObject.cpp index 6fecb0066..a378972d1 100644 --- a/libs/s25main/nodeObjs/noDisappearingMapEnvObject.cpp +++ b/libs/s25main/nodeObjs/noDisappearingMapEnvObject.cpp @@ -36,7 +36,7 @@ noDisappearingMapEnvObject::noDisappearingMapEnvObject(SerializedGameData& sgd, void noDisappearingMapEnvObject::Draw(DrawPoint drawPt) { // Bild - LOADER.GetMapImageN(map_id)->DrawFull(drawPt, GetDrawColor()); + LOADER.GetMapTexture(map_id)->DrawFull(drawPt, GetDrawColor()); // Schatten - LOADER.GetMapImageN(map_id + 100)->DrawFull(drawPt, GetDrawShadowColor()); + LOADER.GetMapTexture(map_id + 100)->DrawFull(drawPt, GetDrawShadowColor()); } diff --git a/libs/s25main/nodeObjs/noFire.cpp b/libs/s25main/nodeObjs/noFire.cpp index c24f97a8c..2f07456d4 100644 --- a/libs/s25main/nodeObjs/noFire.cpp +++ b/libs/s25main/nodeObjs/noFire.cpp @@ -63,8 +63,8 @@ void noFire::Draw(DrawPoint drawPt) if(id < FIREANIMATIONDURATION[world->GetGGS().getSelection(AddonId::BURN_DURATION)] * 2 / 3) { // Loderndes Feuer - LOADER.GetMapImageN(2500 + (isBig ? 8 : 0) + id % 8)->DrawFull(drawPt); - LOADER.GetMapImageN(2530 + (isBig ? 8 : 0) + id % 8)->DrawFull(drawPt, 0xC0101010); + LOADER.GetMapTexture(2500 + (isBig ? 8 : 0) + id % 8)->DrawFull(drawPt); + LOADER.GetMapTexture(2530 + (isBig ? 8 : 0) + id % 8)->DrawFull(drawPt, 0xC0101010); // Feuersound abspielen in zufälligen Intervallen if(VIDEODRIVER.GetTickCount() - last_sound > next_interval) @@ -78,7 +78,7 @@ void noFire::Draw(DrawPoint drawPt) } else { // Schutt - LOADER.GetMapImageN(2524 + (isBig ? 1 : 0))->DrawFull(drawPt); + LOADER.GetMapTexture(2524 + (isBig ? 1 : 0))->DrawFull(drawPt); } } diff --git a/libs/s25main/nodeObjs/noFlag.cpp b/libs/s25main/nodeObjs/noFlag.cpp index 357907e3f..81ce49149 100644 --- a/libs/s25main/nodeObjs/noFlag.cpp +++ b/libs/s25main/nodeObjs/noFlag.cpp @@ -117,7 +117,7 @@ void noFlag::Draw(DrawPoint drawPt) // Waren (von hinten anfangen zu zeichnen) for(unsigned i = wares.size(); i > 0; --i) { - LOADER.GetMapImageN(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(wares[i - 1]->type)) + LOADER.GetMapTexture(WARE_STACK_TEX_MAP_OFFSET + rttr::enum_cast(wares[i - 1]->type)) ->DrawFull(drawPt + WARES_POS[i - 1]); } } diff --git a/libs/s25main/nodeObjs/noSign.cpp b/libs/s25main/nodeObjs/noSign.cpp index 17a818f6e..d40796f00 100644 --- a/libs/s25main/nodeObjs/noSign.cpp +++ b/libs/s25main/nodeObjs/noSign.cpp @@ -59,8 +59,8 @@ void noSign::Draw(DrawPoint drawPt) default: return; } imgId += std::min(resource.getAmount() / 3u, 2u); - LOADER.GetMapPlayerImage(imgId)->DrawFull(drawPt, GetDrawColor()); + LOADER.GetMapTexture(imgId)->DrawFull(drawPt, GetDrawColor()); // Schatten des Schildes - LOADER.GetMapImageN(700)->DrawFull(drawPt, GetDrawShadowColor()); + LOADER.GetMapTexture(700)->DrawFull(drawPt, GetDrawShadowColor()); } diff --git a/libs/s25main/nodeObjs/noSkeleton.cpp b/libs/s25main/nodeObjs/noSkeleton.cpp index 0f203dafb..9b3f1c439 100644 --- a/libs/s25main/nodeObjs/noSkeleton.cpp +++ b/libs/s25main/nodeObjs/noSkeleton.cpp @@ -42,7 +42,7 @@ noSkeleton::noSkeleton(SerializedGameData& sgd, const unsigned obj_id) void noSkeleton::Draw(DrawPoint drawPt) { - LOADER.GetMapImageN(547 + type)->DrawFull(drawPt); + LOADER.GetMapTexture(547 + type)->DrawFull(drawPt); } void noSkeleton::HandleEvent(const unsigned /*id*/) diff --git a/libs/s25main/nodeObjs/noStaticObject.cpp b/libs/s25main/nodeObjs/noStaticObject.cpp index 0a2abde4c..18ba01df9 100644 --- a/libs/s25main/nodeObjs/noStaticObject.cpp +++ b/libs/s25main/nodeObjs/noStaticObject.cpp @@ -75,33 +75,39 @@ BlockingManner noStaticObject::GetBM() const */ void noStaticObject::Draw(DrawPoint drawPt) { - glArchivItem_Bitmap *bitmap = nullptr, *shadow = nullptr; - - if((file == 0xFFFF) && (id == 561)) + if(!textures.bmp) { - LOADER.gateway_cache[GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0) + 1].draw(drawPt); - return; - } else if(file == 0xFFFF) + textures = getTextures(file, id); + RTTR_Assert(textures.bmp); + } + + // Bild zeichnen + textures.bmp->DrawFull(drawPt); + + // Schatten zeichnen + if(textures.shadow) + textures.shadow->DrawFull(drawPt, COLOR_SHADOW); +} + +noStaticObject::Textures noStaticObject::getTextures(unsigned short file, unsigned short id) +{ + Textures textures{}; + if(file == 0xFFFF) { - bitmap = LOADER.GetMapImageN(id); - shadow = LOADER.GetMapImageN(id + 100); + if(id == 561) + textures.bmp = &LOADER.gateway_cache[GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0) + 1]; + else + textures = {LOADER.GetMapTexture(id), LOADER.GetMapTexture(id + 100)}; } else if(file < 7) { static const std::array files = {"mis0bobs", "mis1bobs", "mis2bobs", "mis3bobs", "mis4bobs", "mis5bobs", "charburner_bobs"}; - bitmap = LOADER.GetImageN(files[file], id); + textures.bmp = LOADER.GetTextureN(files[file], id); // Use only shadows where available if(file < 6) - shadow = LOADER.GetImageN(files[file], id + 1); + textures.shadow = LOADER.GetTextureN(files[file], id + 1); } else throw std::runtime_error("Invalid file number for static object"); - RTTR_Assert(bitmap); - - // Bild zeichnen - bitmap->DrawFull(drawPt); - - // Schatten zeichnen - if(shadow) - shadow->DrawFull(drawPt, COLOR_SHADOW); + return textures; } diff --git a/libs/s25main/nodeObjs/noStaticObject.h b/libs/s25main/nodeObjs/noStaticObject.h index aec972c4d..eda45b86b 100644 --- a/libs/s25main/nodeObjs/noStaticObject.h +++ b/libs/s25main/nodeObjs/noStaticObject.h @@ -5,11 +5,17 @@ #pragma once #include "noCoordBase.h" +#include "ogl/ITexture.h" class SerializedGameData; class noStaticObject : public noCoordBase { public: + struct Textures + { + ITexture *bmp, *shadow; + }; + noStaticObject(MapPoint pos, unsigned short id, unsigned short file = 0xFFFF, unsigned char size = 1, NodalObjectType type = NodalObjectType::Object); noStaticObject(SerializedGameData& sgd, unsigned obj_id); @@ -30,8 +36,11 @@ class noStaticObject : public noCoordBase /// zeichnet das Objekt. void Draw(DrawPoint drawPt) override; + static Textures getTextures(unsigned short file, unsigned short id); + protected: unsigned short id; unsigned short file; unsigned char size; + Textures textures{}; }; diff --git a/libs/s25main/ogl/glArchivItem_Bitmap.h b/libs/s25main/ogl/glArchivItem_Bitmap.h index 1af5c102d..b78353964 100644 --- a/libs/s25main/ogl/glArchivItem_Bitmap.h +++ b/libs/s25main/ogl/glArchivItem_Bitmap.h @@ -12,10 +12,7 @@ #include "s25util/colors.h" /// Basisklasse für GL-Bitmapitems. -class glArchivItem_Bitmap : - public virtual libsiedler2::baseArchivItem_Bitmap, - public glArchivItem_BitmapBase, - public ITexture +class glArchivItem_Bitmap : public virtual libsiedler2::baseArchivItem_Bitmap, public glArchivItem_BitmapBase { public: glArchivItem_Bitmap(); @@ -32,9 +29,6 @@ class glArchivItem_Bitmap : /// Draw only percent% of the height of the image void DrawPercent(const DrawPoint& dstPos, unsigned percent, unsigned color = COLOR_WHITE); - Position GetOrigin() const override { return glArchivItem_BitmapBase::GetOrigin(); } - Extent GetSize() const override { return glArchivItem_BitmapBase::GetSize(); } - protected: /// Draw the texture. /// src_w/h default to the full bitmap size diff --git a/libs/s25main/ogl/glArchivItem_BitmapBase.h b/libs/s25main/ogl/glArchivItem_BitmapBase.h index 109497f9b..29dfbad7a 100644 --- a/libs/s25main/ogl/glArchivItem_BitmapBase.h +++ b/libs/s25main/ogl/glArchivItem_BitmapBase.h @@ -5,9 +5,10 @@ #pragma once #include "DrawPoint.h" +#include "ITexture.h" #include "libsiedler2/ArchivItem_BitmapBase.h" -class glArchivItem_BitmapBase : public virtual libsiedler2::ArchivItem_BitmapBase //-V690 +class glArchivItem_BitmapBase : public virtual libsiedler2::ArchivItem_BitmapBase, public ITexture //-V690 { public: glArchivItem_BitmapBase(); @@ -23,8 +24,8 @@ class glArchivItem_BitmapBase : public virtual libsiedler2::ArchivItem_BitmapBas virtual void setInterpolateTexture(bool interpolate); /// Return the "Null point" - DrawPoint GetOrigin() const { return DrawPoint(nx_, ny_); } - Extent GetSize() const { return Extent(getWidth(), getHeight()); } + DrawPoint GetOrigin() const override { return DrawPoint(nx_, ny_); } + Extent GetSize() const override { return Extent(getWidth(), getHeight()); } Extent GetTexSize() const; private: diff --git a/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp b/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp index 5364cddf1..b60261fe9 100644 --- a/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp +++ b/libs/s25main/ogl/glArchivItem_Bitmap_Player.cpp @@ -32,6 +32,11 @@ void glArchivItem_Bitmap_Player::DrawFull(const DrawPoint& dst, unsigned color, DrawFull(Rect(dst, GetSize()), color, player_color); } +void glArchivItem_Bitmap_Player::DrawFull(const Position& dstPos, unsigned color) +{ + DrawFull(dstPos, color, COLOR_WHITE); +} + void glArchivItem_Bitmap_Player::drawForPlayer(const DrawPoint& dst, unsigned playerColor) { DrawFull(dst, COLOR_WHITE, playerColor); diff --git a/libs/s25main/ogl/glArchivItem_Bitmap_Player.h b/libs/s25main/ogl/glArchivItem_Bitmap_Player.h index d7b04ac3c..ec04a9bcb 100644 --- a/libs/s25main/ogl/glArchivItem_Bitmap_Player.h +++ b/libs/s25main/ogl/glArchivItem_Bitmap_Player.h @@ -22,10 +22,11 @@ class glArchivItem_Bitmap_Player : public libsiedler2::ArchivItem_Bitmap_Player, /// Draw the texture in the given rect, stretching if required /// equivalent to Draw(destArea, {0, 0, 0, 0}, color) - void DrawFull(const Rect& destArea, unsigned color = COLOR_WHITE, unsigned player_color = COLOR_WHITE); + void DrawFull(const Rect& destArea, unsigned color, unsigned player_color = COLOR_WHITE); /// Draw the texture to the given position with full size /// equivalent to Draw({dst, 0, 0}, {0, 0, 0, 0}, color, player_color) - void DrawFull(const DrawPoint& dst, unsigned color = COLOR_WHITE, unsigned player_color = COLOR_WHITE); + void DrawFull(const DrawPoint& dst, unsigned color, unsigned player_color); + virtual void DrawFull(const Position& dstPos, unsigned color = COLOR_WHITE) override; /// Draw in player colors void drawForPlayer(const DrawPoint& dst, unsigned playerColor); diff --git a/libs/s25main/world/GameWorldBase.cpp b/libs/s25main/world/GameWorldBase.cpp index a4a8f5e30..b7ea3b15c 100644 --- a/libs/s25main/world/GameWorldBase.cpp +++ b/libs/s25main/world/GameWorldBase.cpp @@ -616,7 +616,7 @@ GameWorldBase::GetSoldiersForSeaAttack(const unsigned char player_attacker, cons { std::vector attackers; // sea attack abgeschaltet per addon? - if(GetGGS().getSelection(AddonId::SEA_ATTACK) == 2) + if(!GetGGS().isEnabled(AddonId::SEA_ATTACK)) return attackers; // Do we have an attackble military building? const auto* milBld = GetSpecObj(pt); diff --git a/libs/s25main/world/GameWorldView.cpp b/libs/s25main/world/GameWorldView.cpp index 7a6d57e48..c44221946 100644 --- a/libs/s25main/world/GameWorldView.cpp +++ b/libs/s25main/world/GameWorldView.cpp @@ -259,12 +259,12 @@ void GameWorldView::DrawGUI(const RoadBuildState& rb, const TerrainRenderer& ter default: break; } } - LOADER.GetMapImageN(mid)->DrawFull(curPos); + LOADER.GetMapTexture(mid)->DrawFull(curPos); } // Currently selected point if(selectedPt == curPt) - LOADER.GetMapImageN(20)->DrawFull(curPos); + LOADER.GetMapTexture(20)->DrawFull(curPos); // not building roads, no further action needed if(rb.mode == RoadBuildMode::Disabled) @@ -278,7 +278,7 @@ void GameWorldView::DrawGUI(const RoadBuildState& rb, const TerrainRenderer& ter // highlight current route pt if(rb.point == curPt) { - LOADER.GetMapImageN(21)->DrawFull(curPos); + LOADER.GetMapTexture(21)->DrawFull(curPos); continue; } @@ -295,7 +295,7 @@ void GameWorldView::DrawGUI(const RoadBuildState& rb, const TerrainRenderer& ter // render special icon for route revert if(!rb.route.empty() && road_points[rb.route.back() + 3u] == curPt) { - LOADER.GetMapImageN(67)->DrawFull(curPos); + LOADER.GetMapTexture(67)->DrawFull(curPos); continue; } @@ -320,13 +320,13 @@ void GameWorldView::DrawGUI(const RoadBuildState& rb, const TerrainRenderer& ter default: id = 60; break; } if(!targetFlag) - LOADER.GetMapImageN(id)->DrawFull(curPos); + LOADER.GetMapTexture(id)->DrawFull(curPos); else { DrawPoint lastPos = GetWorld().GetNodePos(rb.point) - offset + curOffset; DrawPoint halfWayPos = (curPos + lastPos) / 2; - LOADER.GetMapImageN(id)->DrawFull(halfWayPos); - LOADER.GetMapImageN(20)->DrawFull(curPos); + LOADER.GetMapTexture(id)->DrawFull(halfWayPos); + LOADER.GetMapTexture(20)->DrawFull(curPos); } } } @@ -467,7 +467,7 @@ void GameWorldView::DrawConstructionAid(const MapPoint& pt, const DrawPoint& cur BuildingQuality bq = gwv.GetBQ(pt); if(bq != BuildingQuality::Nothing) { - glArchivItem_Bitmap* bm = LOADER.GetMapImageN(49 + rttr::enum_cast(bq)); + auto* bm = LOADER.GetMapTexture(49 + rttr::enum_cast(bq)); // Draw building quality icon bm->DrawFull(curPos); // Show ability to construct military buildings @@ -476,7 +476,7 @@ void GameWorldView::DrawConstructionAid(const MapPoint& pt, const DrawPoint& cur if(!GetWorld().IsMilitaryBuildingNearNode(pt, gwv.GetPlayerId()) && (bq == BuildingQuality::Hut || bq == BuildingQuality::House || bq == BuildingQuality::Castle || bq == BuildingQuality::Harbor)) - LOADER.GetImageN("map_new", 20000)->DrawFull(curPos - DrawPoint(-1, bm->getHeight() + 5)); + LOADER.GetImageN("map_new", 20000)->DrawFull(curPos - DrawPoint(-1, bm->GetSize().y + 5)); } } } diff --git a/tests/s25Main/integration/testFrontierDistance.cpp b/tests/s25Main/integration/testFrontierDistance.cpp index 996b8e661..b665428ad 100644 --- a/tests/s25Main/integration/testFrontierDistance.cpp +++ b/tests/s25Main/integration/testFrontierDistance.cpp @@ -2,9 +2,13 @@ // // SPDX-License-Identifier: GPL-2.0-or-later +#include "GamePlayer.h" #include "buildings/nobMilitary.h" #include "factories/BuildingFactory.h" -#include "worldFixtures/WorldWithGCExecution.h" +#include "worldFixtures/CreateEmptyWorld.h" +#include "worldFixtures/CreateSeaWorld.h" +#include "worldFixtures/WorldFixture.h" +#include "world/MapLoader.h" #include #include @@ -19,10 +23,10 @@ BOOST_AUTO_TEST_SUITE(FrontierDistanceSuite) namespace { -template -struct FrontierWorld : public WorldWithGCExecution<2, T_width, T_height> +template +struct FrontierWorld : public WorldFixture { - using WorldWithGCExecution<2, T_width, T_height>::world; + using WorldFixture::world; MapPoint milBld0Pos, milBld1Pos; nobMilitary *milBld0, *milBld1; @@ -33,9 +37,11 @@ struct FrontierWorld : public WorldWithGCExecution<2, T_width, T_height> const GamePlayer& p1 = world.GetPlayer(1); milBld0Pos = p0.GetHQPos() - MapPoint(0, 2); milBld1Pos = p1.GetHQPos() - MapPoint(0, 2); - // Assumed by distributions and sizes - BOOST_TEST_REQUIRE(milBld0Pos.y == milBld1Pos.y); - // Destroy HQs so only blds are checked + if(std::is_same::value) + { // Assumed by distributions and sizes + BOOST_TEST_REQUIRE(milBld0Pos.y == milBld1Pos.y); + } + // Destroy HQs so only buildings are checked world.DestroyNO(p0.GetHQPos()); world.DestroyNO(p1.GetHQPos()); milBld0 = dynamic_cast( @@ -47,6 +53,7 @@ struct FrontierWorld : public WorldWithGCExecution<2, T_width, T_height> using FrontierWorldSmall = FrontierWorld<34u, 20u>; using FrontierWorldMiddle = FrontierWorld<38u, 20u>; using FrontierWorldBig = FrontierWorld<60u, 20u>; +using FrontierWorldSea = FrontierWorld::width, SmallSeaWorldDefault<2>::height, CreateSeaWorld>; DescIdx GetWaterTerrain(const World& world) { @@ -193,9 +200,8 @@ BOOST_FIXTURE_TEST_CASE(FrontierDistanceFar, FrontierWorldBig) continue; } - MapNode& mapPoint = world.GetNodeWriteable(curPoint); - mapPoint.t1 = tWater; - mapPoint.t2 = tWater; + MapNode& node = world.GetNodeWriteable(curPoint); + node.t1 = node.t2 = tWater; } } @@ -209,10 +215,25 @@ BOOST_FIXTURE_TEST_CASE(FrontierDistanceFar, FrontierWorldBig) FrontierDistance distance1 = milBld1->GetFrontierDistance(); BOOST_TEST_REQUIRE(distance0 == distance1); - BOOST_TEST_REQUIRE(distance0 == FrontierDistance::Far); // everytime inland + BOOST_TEST_REQUIRE(distance0 == FrontierDistance::Far); // every time inland } } +BOOST_FIXTURE_TEST_CASE(FrontierDistanceHarbor, FrontierWorldSea) +{ + // With sea attacks + this->ggs.setSelection(AddonId::SEA_ATTACK, 0); + milBld0->LookForEnemyBuildings(milBld1); + BOOST_TEST(milBld0->GetFrontierDistance() == FrontierDistance::Harbor); + this->ggs.setSelection(AddonId::SEA_ATTACK, 1); + milBld0->LookForEnemyBuildings(milBld1); + BOOST_TEST(milBld0->GetFrontierDistance() == FrontierDistance::Harbor); + // With sea attacks disabled + this->ggs.setSelection(AddonId::SEA_ATTACK, 2); + milBld0->LookForEnemyBuildings(milBld1); + BOOST_TEST(milBld0->GetFrontierDistance() == FrontierDistance::Far); +} + BOOST_FIXTURE_TEST_CASE(FrontierDistanceIslandTest, FrontierWorldMiddle) { const DescIdx tWater = GetWaterTerrain(world); @@ -274,7 +295,7 @@ BOOST_FIXTURE_TEST_CASE(FrontierDistanceIslandTest, FrontierWorldMiddle) // | || | // --------------------------------------------- // -using WorldBig = WorldWithGCExecution<2u, 60u, 60u>; +using WorldBig = WorldFixture; BOOST_FIXTURE_TEST_CASE(FrontierDistanceBug_815, WorldBig) { this->ggs.setSelection(AddonId::FRONTIER_DISTANCE_REACHABLE, 1); diff --git a/tests/s25Main/lua/testLua.cpp b/tests/s25Main/lua/testLua.cpp index 9a4984268..1a049f874 100644 --- a/tests/s25Main/lua/testLua.cpp +++ b/tests/s25Main/lua/testLua.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "GameWithLuaAccess.h" +#include "Loader.h" #include "PointOutput.h" #include "RttrForeachPt.h" #include "buildings/noBuildingSite.h" @@ -557,6 +558,7 @@ BOOST_AUTO_TEST_CASE(World) { LogAccessor logAcc; initWorld(); + LOADER.LoadDummyMapFiles(); executeLua("world = rttr:GetWorld()"); const MapPoint envPt(15, 12); @@ -564,46 +566,54 @@ BOOST_AUTO_TEST_CASE(World) executeLua(boost::format("world:AddEnvObject(%1%, %2%, 500)") % envPt.x % envPt.y); const noEnvObject* obj = world.GetSpecObj(envPt); BOOST_TEST_REQUIRE(obj); - BOOST_TEST_REQUIRE(obj->GetItemID() == 500u); - BOOST_TEST_REQUIRE(obj->GetItemFile() == 0xFFFFu); + BOOST_TEST(obj->GetItemID() == 500u); + BOOST_TEST(obj->GetItemFile() == 0xFFFFu); // Replace and test wrap around (envPt2==envPt1) const Position envPt2(envPt.x + world.GetWidth(), envPt.y - world.GetHeight()); BOOST_TEST_REQUIRE(world.MakeMapPoint(envPt2) == envPt); executeLua(boost::format("world:AddEnvObject(%1%, %2%, 1, 2)") % envPt2.x % envPt2.y); obj = world.GetSpecObj(envPt); BOOST_TEST_REQUIRE(obj); - BOOST_TEST_REQUIRE(obj->GetItemID() == 1u); - BOOST_TEST_REQUIRE(obj->GetItemFile() == 2u); + BOOST_TEST(obj->GetItemID() == 1u); + BOOST_TEST(obj->GetItemFile() == 2u); // ID only const MapPoint envPt3(envPt.x + 5, envPt.y); executeLua(boost::format("world:AddStaticObject(%1%, %2%, 501)") % envPt3.x % envPt3.y); const noStaticObject* obj2 = world.GetSpecObj(envPt3); BOOST_TEST_REQUIRE(obj2); - BOOST_TEST_REQUIRE(obj2->GetGOT() == GO_Type::Staticobject); - BOOST_TEST_REQUIRE(obj2->GetItemID() == 501u); - BOOST_TEST_REQUIRE(obj2->GetItemFile() == 0xFFFFu); - BOOST_TEST_REQUIRE(obj2->GetSize() == 1u); + BOOST_TEST(obj2->GetGOT() == GO_Type::Staticobject); + BOOST_TEST(obj2->GetItemID() == 501u); + BOOST_TEST(obj2->GetItemFile() == 0xFFFFu); + BOOST_TEST(obj2->GetSize() == 1u); // ID and File (replace env obj) executeLua(boost::format("world:AddStaticObject(%1%, %2%, 5, 3)") % envPt2.x % envPt2.y); obj2 = world.GetSpecObj(envPt); BOOST_TEST_REQUIRE(obj2); - BOOST_TEST_REQUIRE(obj2->GetGOT() == GO_Type::Staticobject); - BOOST_TEST_REQUIRE(obj2->GetItemID() == 5u); - BOOST_TEST_REQUIRE(obj2->GetItemFile() == 3u); - BOOST_TEST_REQUIRE(obj2->GetSize() == 1u); + BOOST_TEST(obj2->GetGOT() == GO_Type::Staticobject); + BOOST_TEST(obj2->GetItemID() == 5u); + BOOST_TEST(obj2->GetItemFile() == 3u); + BOOST_TEST(obj2->GetSize() == 1u); // ID, File and Size (replace static obj) executeLua(boost::format("world:AddStaticObject(%1%, %2%, 5, 3, 2)") % envPt2.x % envPt2.y); obj2 = world.GetSpecObj(envPt); BOOST_TEST_REQUIRE(obj2); - BOOST_TEST_REQUIRE(obj2->GetGOT() == GO_Type::Staticobject); - BOOST_TEST_REQUIRE(obj2->GetItemID() == 5u); - BOOST_TEST_REQUIRE(obj2->GetItemFile() == 3u); - BOOST_TEST_REQUIRE(obj2->GetSize() == 2u); + BOOST_TEST(obj2->GetGOT() == GO_Type::Staticobject); + BOOST_TEST(obj2->GetItemID() == 5u); + BOOST_TEST(obj2->GetItemFile() == 3u); + BOOST_TEST(obj2->GetSize() == 2u); // Invalid Size - BOOST_REQUIRE_THROW(executeLua(boost::format("world:AddStaticObject(%1%, %2%, 5, 3, 3)") % envPt2.x % envPt2.y), - std::runtime_error); + BOOST_CHECK_THROW(executeLua(boost::format("world:AddStaticObject(%1%, %2%, 5, 3, 3)") % envPt2.x % envPt2.y), + std::runtime_error); RTTR_REQUIRE_LOG_CONTAINS("Invalid size", false); + // Invalid File + BOOST_CHECK_THROW(executeLua(boost::format("world:AddEnvObject(%1%, %2%, 5, 7)") % envPt2.x % envPt2.y), + std::runtime_error); + RTTR_REQUIRE_LOG_CONTAINS("Invalid object ", false); + // Invalid Id + BOOST_CHECK_THROW(executeLua(boost::format("world:AddEnvObject(%1%, %2%, 50000)") % envPt2.x % envPt2.y), + std::runtime_error); + RTTR_REQUIRE_LOG_CONTAINS("Invalid object ", false); // Can't replace buildings executeLua(boost::format("world:AddEnvObject(%1%, %2%, 1, 2)") % hqPos.x % hqPos.y); @@ -614,7 +624,7 @@ BOOST_AUTO_TEST_CASE(World) executeLua(boost::format("world:AddEnvObject(%1%, %2%, 5, 3)") % envPt2.x % envPt2.y); obj2 = world.GetSpecObj(envPt); BOOST_TEST_REQUIRE(obj2); - BOOST_TEST_REQUIRE(obj2->GetGOT() == GO_Type::Envobject); + BOOST_TEST(obj2->GetGOT() == GO_Type::Envobject); MapPoint animalPos(20, 12); const auto figs = world.GetFigures(animalPos); @@ -623,12 +633,12 @@ BOOST_AUTO_TEST_CASE(World) BOOST_TEST_REQUIRE(figs.size() == 1u); const noAnimal* animal = dynamic_cast(&*figs.begin()); BOOST_TEST_REQUIRE(animal); - BOOST_TEST_REQUIRE(animal->GetSpecies() == Species::Deer); //-V522 + BOOST_TEST(animal->GetSpecies() == Species::Deer); //-V522 executeLua(boost::format("world:AddAnimal(%1%, %2%, SPEC_FOX)") % animalPos.x % animalPos.y); BOOST_TEST_REQUIRE(figs.size() == 2u); animal = dynamic_cast(&*(++figs.begin())); BOOST_TEST_REQUIRE(animal); - BOOST_TEST_REQUIRE(animal->GetSpecies() == Species::Fox); + BOOST_TEST(animal->GetSpecies() == Species::Fox); } BOOST_AUTO_TEST_CASE(WorldEvents) diff --git a/tests/s25Main/simple/testGameMessages.cpp b/tests/s25Main/simple/testGameMessages.cpp new file mode 100644 index 000000000..90ade754e --- /dev/null +++ b/tests/s25Main/simple/testGameMessages.cpp @@ -0,0 +1,308 @@ +// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org) +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "JoinPlayerInfo.h" +#include "network/GameMessages.h" +#include "gameTypes/GameTypesOutput.h" +#include "gameTypes/PlayerState.h" +#include "rttr/test/random.hpp" +#include "s25util/boostTestHelpers.h" +#include + +static bool operator==(const JoinPlayerInfo& lhs, const JoinPlayerInfo& rhs) +{ + const auto getMembers = [](const JoinPlayerInfo& info) { + return std::tie(info.ps, info.aiInfo, info.name, info.name, info.color, info.team, info.isHost, info.ping, + info.originName, info.isReady); + }; + return getMembers(lhs) == getMembers(rhs); +} + +// LCOV_EXCL_START +BOOST_TEST_DONT_PRINT_LOG_VALUE(AI::Info) +BOOST_TEST_DONT_PRINT_LOG_VALUE(JoinPlayerInfo) + +template +static std::enable_if_t::value, std::ostream&> operator<<(std::ostream& os, T enumVal) +{ + return os << rttr::enum_cast(enumVal); +} +// LCOV_EXCL_STOP + +BOOST_AUTO_TEST_SUITE(GameMessages) + +template +auto serializeDeserializeMessage(const TMsg& msgIn) +{ + static Serializer ser; + ser.Clear(); + msgIn.Serialize(ser); + Message* msgOut(GameMessage::create_game(msgIn.getId())); + BOOST_TEST_REQUIRE(msgOut); + std::unique_ptr msgResult(dynamic_cast(msgOut)); + BOOST_TEST_REQUIRE(!!msgResult); + Serializer serOut(ser.GetData(), ser.GetLength()); + msgOut->Deserialize(serOut); + BOOST_TEST(serOut.GetBytesLeft() == 0u); + return msgResult; +} + +BOOST_AUTO_TEST_CASE(Serialization) +{ + using rttr::test::randomBool; + using rttr::test::randomEnum; + using rttr::test::randomValue; + using rttr::test::randString; + + { + const GameMessage_Ping msgIn(randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + } + { + const auto msgOut = serializeDeserializeMessage(GameMessage_Pong()); + BOOST_TEST(msgOut); // Only exist + } + { + const GameMessage_Server_Type msgIn(randomEnum(), randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->type == msgIn.type); + BOOST_TEST(msgOut->revision == msgIn.revision); + } + { + const GameMessage_Server_TypeOK msgIn(randomEnum(), randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->err_code == msgIn.err_code); + BOOST_TEST(msgOut->version == msgIn.version); + } + { + const GameMessage_Server_Password msgIn(randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->password == msgIn.password); + } + { + const GameMessage_Server_Name msgIn(randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->name == msgIn.name); + } + { + const GameMessage_Server_Start msgIn(randomValue(), randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->random_init == msgIn.random_init); + BOOST_TEST(msgOut->firstNwf == msgIn.firstNwf); + BOOST_TEST(msgOut->cmdDelay == msgIn.cmdDelay); + } + { + const GameMessage_Countdown msgIn(randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->countdown == msgIn.countdown); + } + { + const GameMessage_CancelCountdown msgIn(randomBool()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->error == msgIn.error); + } + { + const GameMessage_Server_Async msgIn(std::vector(randomValue(0, 3), randomValue())); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->checksums == msgIn.checksums, boost::test_tools::per_element()); + } + { + const GameMessage_Player_Id msgIn(randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + } + { + const GameMessage_Player_Name msgIn(randomValue(), randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->playername == msgIn.playername); + } + { + std::vector playerInfos(randomValue(1, 8)); + for(JoinPlayerInfo& player : playerInfos) + { + player.ps = randomEnum(); + player.aiInfo.type = randomEnum(); + player.aiInfo.level = randomEnum(); + player.name = randString(); + player.nation = randomEnum(); + player.color = randomValue(); + player.team = randomEnum(); + player.isHost = randomBool(); + player.ping = randomValue(); + player.originName = randString(); + player.isReady = randomBool(); + } + const GameMessage_Player_List msgIn(playerInfos); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->playerInfos == msgIn.playerInfos, boost::test_tools::per_element()); + } + { + const GameMessage_Player_State msgIn(randomValue(), randomEnum(), + {randomEnum(), randomEnum()}); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->aiInfo == msgIn.aiInfo); + } + { + const GameMessage_Player_Nation msgIn(randomValue(), randomEnum()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->nation == msgIn.nation); + } + { + const GameMessage_Player_Team msgIn(randomValue(), randomEnum()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->team == msgIn.team); + } + { + const GameMessage_Player_Color msgIn(randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->color == msgIn.color); + } + { + const GameMessage_Player_Kicked msgIn(randomValue(), randomEnum(), + randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->cause == msgIn.cause); + BOOST_TEST(msgOut->param == msgIn.param); + } + { + const GameMessage_Player_Ping msgIn(randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->ping == msgIn.ping); + } + { + const GameMessage_Player_New msgIn(randomValue(), randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->name == msgIn.name); + } + { + const GameMessage_Player_Ready msgIn(randomValue(), randomBool()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->ready == msgIn.ready); + } + { + const GameMessage_Player_Swap msgIn(randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->player2 == msgIn.player2); + } + { + const GameMessage_Player_SwapConfirm msgIn(randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->player == msgIn.player); + BOOST_TEST(msgOut->player2 == msgIn.player2); + } + { + const GameMessage_Map_Info msgIn(randString(), randomEnum(), randomValue(), + randomValue(), randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->filename == msgIn.filename); + BOOST_TEST(msgOut->mt == msgIn.mt); + BOOST_TEST(msgOut->mapLen == msgIn.mapLen); + BOOST_TEST(msgOut->mapCompressedLen == msgIn.mapCompressedLen); + BOOST_TEST(msgOut->luaLen == msgIn.luaLen); + BOOST_TEST(msgOut->luaCompressedLen == msgIn.luaCompressedLen); + } + { + const GameMessage_MapRequest msgIn(randomBool()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->requestInfo == msgIn.requestInfo); + } + { + std::vector data(randomValue(1, 20)); + for(auto& c : data) + c = randomValue(); + const GameMessage_Map_Data msgIn(randomBool(), randomValue(), data.data(), data.size()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->isMapData == msgIn.isMapData); + BOOST_TEST(msgOut->offset == msgIn.offset); + BOOST_TEST(msgOut->data == msgIn.data); + } + { + const GameMessage_Map_Checksum msgIn(randomValue(), randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->mapChecksum == msgIn.mapChecksum); + BOOST_TEST(msgOut->luaChecksum == msgIn.luaChecksum); + } + { + const GameMessage_Map_ChecksumOK msgIn(randomBool(), randomBool()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->correct == msgIn.correct); + BOOST_TEST(msgOut->retryAllowed == msgIn.retryAllowed); + } + { + GameMessage_GGSChange msgIn(GlobalGameSettings{}); + msgIn.ggs.exploration = randomEnum(); // Just set (and test) any, not the whole struct + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->ggs.exploration == msgIn.ggs.exploration); + } + { + const GameMessage_Speed msgIn(randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->gf_length == msgIn.gf_length); + } + { + const GameMessage_Server_NWFDone msgIn(randomValue(), randomValue(), + randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->gf == msgIn.gf); + BOOST_TEST(msgOut->gf_length == msgIn.gf_length); + BOOST_TEST(msgOut->nextNWF == msgIn.nextNWF); + } + { + const GameMessage_Pause msgIn(randomBool()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->paused == msgIn.paused); + } + { + const GameMessage_SkipToGF msgIn(randomValue()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->targetGF == msgIn.targetGF); + } + { + const auto msgOut = serializeDeserializeMessage(GameMessage_GetAsyncLog()); + BOOST_TEST(msgOut); // Just exist + } + { + const GameMessage_AsyncLog msgIn(randString()); + const auto msgOut = serializeDeserializeMessage(msgIn); + BOOST_TEST(msgOut->addData == msgIn.addData); + BOOST_TEST(!msgOut->last); + BOOST_TEST(msgOut->entries.empty()); + + std::vector async_log(randomValue(1, 5)); + for(auto& entry : async_log) + { + entry.counter = randomValue(); + entry.maxExcl = randomValue(); + entry.srcName = randString(); + entry.srcLine = randomValue(); + entry.objId = randomValue(); + } + const GameMessage_AsyncLog msgIn2(std::move(async_log), randomBool()); + const auto msgOut2 = serializeDeserializeMessage(msgIn2); + BOOST_TEST(msgOut2->addData.empty()); + BOOST_TEST(msgOut2->last == msgIn2.last); + BOOST_TEST_REQUIRE(msgOut2->entries.size() == msgIn2.entries.size()); + for(unsigned i = 0; i < msgIn2.entries.size(); i++) + { + BOOST_TEST(msgOut2->entries[i].counter == msgIn2.entries[i].counter); + BOOST_TEST(msgOut2->entries[i].maxExcl == msgIn2.entries[i].maxExcl); + BOOST_TEST(msgOut2->entries[i].srcName == msgIn2.entries[i].srcName); + BOOST_TEST(msgOut2->entries[i].srcLine == msgIn2.entries[i].srcLine); + BOOST_TEST(msgOut2->entries[i].objId == msgIn2.entries[i].objId); + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/s25Main/worldFixtures/CreateSeaWorld.cpp b/tests/s25Main/worldFixtures/CreateSeaWorld.cpp index 3edbc8225..92abb04ab 100644 --- a/tests/s25Main/worldFixtures/CreateSeaWorld.cpp +++ b/tests/s25Main/worldFixtures/CreateSeaWorld.cpp @@ -41,7 +41,7 @@ bool PlaceHarbor(MapPoint pt, GameWorldBase& world, std::vector& harbo } } } - return false; + return false; // LCOV_EXCL_LINE } } // namespace @@ -81,14 +81,21 @@ bool CreateSeaWorld::operator()(GameWorld& world) const * WWWWWWWWWWWWWWWWWWWWWWW Height of water: Offset * WWWWWWWWWWWWWWWWWWWWWWW */ + const auto minMapSide = std::min(size_.x, size_.y); // Init some land stripes of size 15 (a bit less than the HQ radius) - const MapCoord offset = 7; - const MapCoord landSize = 15; + MapCoord offset = 7; + MapCoord landSize = 15; // We need the offset at each side, the land on each side // and at least the same amount of water between the land - const MapCoord minSize = landSize * 3 + offset * 2; - if(size_.x < minSize || size_.y < minSize) - throw std::runtime_error("World to small"); // LCOV_EXCL_LINE + MapCoord minSize = landSize * 3 + offset * 2; + if(minMapSide < minSize) + { + offset /= 2; + landSize /= 2; + minSize = landSize * 3 + offset * 2; + if(minMapSide < minSize) + throw std::runtime_error("World to small"); // LCOV_EXCL_LINE + } t = DescIdx(0); for(; t.value < desc.terrain.size(); t.value++) { @@ -125,28 +132,23 @@ bool CreateSeaWorld::operator()(GameWorld& world) const } // Place HQs at top, left, right, bottom - std::vector hqPositions; - hqPositions.push_back(MapPoint(size_.x / 2, offset + landSize / 2)); - hqPositions.push_back(MapPoint(offset + landSize / 2, size_.y / 2)); - hqPositions.push_back(MapPoint(size_.x - offset - landSize / 2, size_.y / 2)); - hqPositions.push_back(MapPoint(size_.x / 2, size_.y - offset - landSize / 2)); + std::vector hqPositions{ + MapPoint(size_.x / 2, offset + landSize / 2), MapPoint(offset + landSize / 2, size_.y / 2), + MapPoint(size_.x - offset - landSize / 2, size_.y / 2), MapPoint(size_.x / 2, size_.y - offset - landSize / 2)}; std::vector harbors; - // Place harbors - for(MapPoint pt : hqPositions) + // Place harbors (top HQ) + BOOST_TEST_REQUIRE(PlaceHarbor(hqPositions[0] - MapPoint(0, landSize / 2), world, harbors)); + BOOST_TEST_REQUIRE(PlaceHarbor(hqPositions[0] + MapPoint(0, landSize / 2), world, harbors)); + // Place harbors (left&right HQs) + for(MapPoint pt : {hqPositions[1], hqPositions[2]}) { - unsigned harborsPlaced = 0; - if(PlaceHarbor(pt - MapPoint(landSize / 2, 0), world, harbors)) - ++harborsPlaced; - if(PlaceHarbor(pt + MapPoint(landSize / 2, 0), world, harbors)) - ++harborsPlaced; - if(PlaceHarbor(pt - MapPoint(0, landSize / 2), world, harbors)) - ++harborsPlaced; - if(PlaceHarbor(pt + MapPoint(0, landSize / 2), world, harbors)) - ++harborsPlaced; - // Exactly 2 harbors should be placed per HQ (left and right or above and below) - RTTR_Assert(harborsPlaced == 2); + BOOST_TEST_REQUIRE(PlaceHarbor(pt - MapPoint(landSize / 2, 0), world, harbors)); + BOOST_TEST_REQUIRE(PlaceHarbor(pt + MapPoint(landSize / 2, 0), world, harbors)); } + // Place harbors (bottom HQ) + BOOST_TEST_REQUIRE(PlaceHarbor(hqPositions[3] - MapPoint(0, landSize / 2), world, harbors)); + BOOST_TEST_REQUIRE(PlaceHarbor(hqPositions[3] + MapPoint(0, landSize / 2), world, harbors)); BOOST_TEST_REQUIRE(MapLoader::InitSeasAndHarbors(world, harbors));