From e505aab29ab6e347f4c2207dc79a74b70ca0aa14 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Wed, 1 May 2024 00:49:33 +0200 Subject: [PATCH] scrolling works --- client/lobby/CSelectionBase.cpp | 72 +++++++++++++++++++++++++------- client/lobby/CSelectionBase.h | 8 +++- lib/networkPacks/PacksForLobby.h | 2 + server/NetPacksLobbyServer.cpp | 27 +++++++----- 4 files changed, 83 insertions(+), 26 deletions(-) diff --git a/client/lobby/CSelectionBase.cpp b/client/lobby/CSelectionBase.cpp index 6907c17bb..aefcdf4c0 100644 --- a/client/lobby/CSelectionBase.cpp +++ b/client/lobby/CSelectionBase.cpp @@ -403,25 +403,35 @@ PvPBox::PvPBox(const Rect & rect) backgroundTexture->playerColored(PlayerColor(1)); backgroundBorder = std::make_shared(Rect(0, 0, rect.w, rect.h), ColorRGBA(0, 0, 0, 64), ColorRGBA(96, 96, 96, 255), 1); - factionselector = std::make_shared(Point(5, 3)); + factionSelector = std::make_shared(Point(5, 3)); - buttonFlipCoin = std::make_shared(Point(203, 6), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("flip coin"), [](){ + auto getBannedTowns = [this](){ + std::vector bannedTowns; + for(auto & town : factionSelector->townsEnabled) + if(!town.second) + bannedTowns.push_back(town.first); + return bannedTowns; + }; + + buttonFlipCoin = std::make_shared(Point(190, 6), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("flip coin"), [](){ LobbyPvPAction lpa; lpa.action = LobbyPvPAction::COIN; CSH->sendLobbyPack(lpa); }, EShortcut::NONE); buttonFlipCoin->setTextOverlay("Flip coin2", EFonts::FONT_SMALL, Colors::WHITE); - buttonRandomTown = std::make_shared(Point(203, 31), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town"), [](){ + buttonRandomTown = std::make_shared(Point(190, 31), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town"), [getBannedTowns](){ LobbyPvPAction lpa; lpa.action = LobbyPvPAction::RANDOM_TOWN; + lpa.bannedTowns = getBannedTowns(); CSH->sendLobbyPack(lpa); }, EShortcut::NONE); buttonRandomTown->setTextOverlay("random town", EFonts::FONT_SMALL, Colors::WHITE); - buttonRandomTownVs = std::make_shared(Point(203, 56), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town vs"), [](){ + buttonRandomTownVs = std::make_shared(Point(190, 56), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town vs"), [getBannedTowns](){ LobbyPvPAction lpa; lpa.action = LobbyPvPAction::RANDOM_TOWN_VS; + lpa.bannedTowns = getBannedTowns(); CSH->sendLobbyPack(lpa); }, EShortcut::NONE); buttonRandomTownVs->setTextOverlay("random town vs", EFonts::FONT_SMALL, Colors::WHITE); @@ -433,20 +443,46 @@ FactionSelector::FactionSelector(const Point & loc) pos += loc; setRedrawParent(true); + int count = 0; + CGI->factions()->forEach([this, &count](const Faction *entity, bool &stop){ + if(!entity->hasTown()) + return; + townsEnabled[entity->getFaction()] = true; + count++; + }); + + auto divisionRoundUp = [](int x, int y){ return (x + (y - 1)) / y; }; + slider = std::make_shared(Point(144, 0), 96, std::bind(&FactionSelector::sliderMove, this, _1), 3, divisionRoundUp(count, 3), 0, Orientation::VERTICAL, CSlider::BLUE); + slider->setPanningStep(24); + slider->setScrollBounds(Rect(-144, 0, slider->pos.x - pos.x + slider->pos.w, slider->pos.h)); + + updateListItems(); +} + +void FactionSelector::updateListItems() +{ + OBJ_CONSTRUCTION; + int line = slider->getValue(); + + towns.clear(); + townsArea.clear(); + int x = 0, y = 0; - CGI->factions()->forEach([this, &x, &y](const Faction *entity, bool &stop){ + CGI->factions()->forEach([this, &x, &y, line](const Faction *entity, bool &stop){ if(!entity->hasTown()) return; - FactionID factionID = entity->getFaction(); - auto getImageIndex = [](FactionID factionID, bool enabled){ return (*CGI->townh)[factionID]->town->clientInfo.icons[true][!enabled] + 2; }; - towns[factionID] = std::make_shared(AnimationPath::builtin("ITPA"), getImageIndex(factionID, true), 0, 48 * x, 32 * y); - townsArea[factionID] = std::make_shared(Rect(48 * x, 32 * y, 48, 32), [this, getImageIndex, factionID](){ - townsEnabled[factionID] = !townsEnabled[factionID]; - towns[factionID]->setFrame(getImageIndex(factionID, townsEnabled[factionID])); - redraw(); - }); - townsEnabled[factionID] = true; + if(y >= line && (y - line) < 3) + { + FactionID factionID = entity->getFaction(); + auto getImageIndex = [](FactionID factionID, bool enabled){ return (*CGI->townh)[factionID]->town->clientInfo.icons[true][!enabled] + 2; }; + towns[factionID] = std::make_shared(AnimationPath::builtin("ITPA"), getImageIndex(factionID, townsEnabled[factionID]), 0, 48 * x, 32 * (y - line)); + townsArea[factionID] = std::make_shared(Rect(48 * x, 32 * (y - line), 48, 32), [this, getImageIndex, factionID](){ + townsEnabled[factionID] = !townsEnabled[factionID]; + towns[factionID]->setFrame(getImageIndex(factionID, townsEnabled[factionID])); + redraw(); + }); + } if (x < 2) x++; @@ -458,6 +494,14 @@ FactionSelector::FactionSelector(const Point & loc) }); } +void FactionSelector::sliderMove(int slidPos) +{ + if(!slider) + return; // ignore spurious call when slider is being created + updateListItems(); + redraw(); +} + CFlagBox::CFlagBox(const Rect & rect) : CIntObject(SHOW_POPUP) { diff --git a/client/lobby/CSelectionBase.h b/client/lobby/CSelectionBase.h index d309e05eb..04cc8e677 100644 --- a/client/lobby/CSelectionBase.h +++ b/client/lobby/CSelectionBase.h @@ -148,7 +148,7 @@ class PvPBox : public CIntObject std::shared_ptr backgroundTexture; std::shared_ptr backgroundBorder; - std::shared_ptr factionselector; + std::shared_ptr factionSelector; std::shared_ptr buttonFlipCoin; std::shared_ptr buttonRandomTown; @@ -161,10 +161,14 @@ class FactionSelector : public CIntObject { std::map> towns; std::map> townsArea; - std::map townsEnabled; std::shared_ptr slider; + void sliderMove(int slidPos); + void updateListItems(); + public: + std::map townsEnabled; + FactionSelector(const Point & loc); }; diff --git a/lib/networkPacks/PacksForLobby.h b/lib/networkPacks/PacksForLobby.h index 93afe7ed2..defb0a3c1 100644 --- a/lib/networkPacks/PacksForLobby.h +++ b/lib/networkPacks/PacksForLobby.h @@ -348,6 +348,7 @@ struct DLL_LINKAGE LobbyPvPAction : public CLobbyPackToServer enum EAction : ui8 { NONE, COIN, RANDOM_TOWN, RANDOM_TOWN_VS } action = NONE; + std::vector bannedTowns; void visitTyped(ICPackVisitor & visitor) override; @@ -355,6 +356,7 @@ struct DLL_LINKAGE LobbyPvPAction : public CLobbyPackToServer template void serialize(Handler &h) { h & action; + h & bannedTowns; } }; diff --git a/server/NetPacksLobbyServer.cpp b/server/NetPacksLobbyServer.cpp index eb7c177fb..3c6c81678 100644 --- a/server/NetPacksLobbyServer.cpp +++ b/server/NetPacksLobbyServer.cpp @@ -372,25 +372,32 @@ void ApplyOnServerNetPackVisitor::visitLobbyForceSetPlayer(LobbyForceSetPlayer & void ApplyOnServerNetPackVisitor::visitLobbyPvPAction(LobbyPvPAction & pack) { - std::set allowedFactions; - for(auto & player : srv.mi->mapHeader->players) - { - std::set tmpAllowedFactions = player.allowedFactions; - std::set_union(std::begin(tmpAllowedFactions), std::end(tmpAllowedFactions), std::begin(allowedFactions), std::end(allowedFactions), std::inserter(allowedFactions, std::begin(allowedFactions))); - } + std::vector allowedFactions; - std::vector randomFactions; - std::sample(allowedFactions.begin(), allowedFactions.end(), std::back_inserter(randomFactions), 2, std::mt19937{std::random_device{}()}); + VLC->townh->forEach([pack, &allowedFactions](const Faction *entity, bool &stop){ + if(!entity->hasTown()) + return; + if(std::find(pack.bannedTowns.begin(), pack.bannedTowns.end(), entity->getId()) == pack.bannedTowns.end()) { + allowedFactions.push_back(entity->getId()); + } + }); + + std::vector randomFaction1; + std::sample(allowedFactions.begin(), allowedFactions.end(), std::back_inserter(randomFaction1), 1, std::mt19937{std::random_device{}()}); + std::vector randomFaction2; + std::sample(allowedFactions.begin(), allowedFactions.end(), std::back_inserter(randomFaction2), 1, std::mt19937{std::random_device{}()}); switch(pack.action) { case LobbyPvPAction::COIN: srv.announceTxt("Coin - " + std::to_string(std::rand()%2)); break; case LobbyPvPAction::RANDOM_TOWN: - srv.announceTxt("Faction - " + VLC->townh->getById(randomFactions[0])->getNameTranslated()); + if(allowedFactions.size()) + srv.announceTxt("Faction - " + VLC->townh->getById(randomFaction1[0])->getNameTranslated()); break; case LobbyPvPAction::RANDOM_TOWN_VS: - srv.announceTxt("Factions - " + VLC->townh->getById(randomFactions[0])->getNameTranslated() + " vs. " + VLC->townh->getById(randomFactions[randomFactions.size() > 1 ? 1 : 0])->getNameTranslated()); + if(allowedFactions.size()) + srv.announceTxt("Factions - " + VLC->townh->getById(randomFaction1[0])->getNameTranslated() + " vs. " + VLC->townh->getById(randomFaction2[0])->getNameTranslated()); break; } result = true;