From e22d15b1d8f3f629c59d785935d51fc29f27d8f7 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:47:26 +0300 Subject: [PATCH 1/2] manageBackpackArtifacts --- CCallback.cpp | 18 ++++++++ CCallback.h | 6 +++ client/windows/CHeroBackpackWindow.cpp | 7 +++ client/windows/CHeroBackpackWindow.h | 1 + server/CGameHandler.cpp | 64 ++++++++++++++++++++++---- server/CGameHandler.h | 3 +- server/NetPacksServer.cpp | 17 +------ 7 files changed, 89 insertions(+), 27 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index 8d2709f3d..b63ab9dc9 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -192,6 +192,24 @@ void CCallback::scrollBackpackArtifacts(ObjectInstanceID hero, bool left) sendRequest(&mba); } +void CCallback::sortBackpackArtifactsBySlot(const ObjectInstanceID hero) +{ + ManageBackpackArtifacts mba(hero, ManageBackpackArtifacts::ManageCmd::SORT_BY_SLOT); + sendRequest(&mba); +} + +void CCallback::sortBackpackArtifactsByCost(const ObjectInstanceID hero) +{ + ManageBackpackArtifacts mba(hero, ManageBackpackArtifacts::ManageCmd::SORT_BY_COST); + sendRequest(&mba); +} + +void CCallback::sortBackpackArtifactsByClass(const ObjectInstanceID hero) +{ + ManageBackpackArtifacts mba(hero, ManageBackpackArtifacts::ManageCmd::SORT_BY_CLASS); + sendRequest(&mba); +} + void CCallback::manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) { ManageEquippedArtifacts mea(hero, costumeIndex, saveCostume); diff --git a/CCallback.h b/CCallback.h index a934113ce..c2a439595 100644 --- a/CCallback.h +++ b/CCallback.h @@ -92,6 +92,9 @@ public: //virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0; virtual void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) = 0; + virtual void sortBackpackArtifactsBySlot(const ObjectInstanceID hero) = 0; + virtual void sortBackpackArtifactsByCost(const ObjectInstanceID hero) = 0; + virtual void sortBackpackArtifactsByClass(const ObjectInstanceID hero) = 0; virtual void manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) = 0; virtual void assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0; virtual void eraseArtifactByClient(const ArtifactLocation & al)=0; @@ -179,6 +182,9 @@ public: void assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override; void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) override; + void sortBackpackArtifactsBySlot(const ObjectInstanceID hero) override; + void sortBackpackArtifactsByCost(const ObjectInstanceID hero) override; + void sortBackpackArtifactsByClass(const ObjectInstanceID hero) override; void manageHeroCostume(ObjectInstanceID hero, size_t costumeIdx, bool saveCostume) override; void eraseArtifactByClient(const ArtifactLocation & al) override; bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override; diff --git a/client/windows/CHeroBackpackWindow.cpp b/client/windows/CHeroBackpackWindow.cpp index 361350a72..ee07f2f60 100644 --- a/client/windows/CHeroBackpackWindow.cpp +++ b/client/windows/CHeroBackpackWindow.cpp @@ -20,6 +20,8 @@ #include "render/Canvas.h" #include "CPlayerInterface.h" +#include "../../CCallback.h" + #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/networkPacks/ArtifactLocation.h" @@ -41,11 +43,16 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std: }; addSet(arts); arts->setHero(hero); + quitButton = std::make_shared(Point(), AnimationPath::builtin("IOKAY32.def"), CButton::tooltip(""), [this]() { WindowBase::close(); }, EShortcut::GLOBAL_RETURN); pos.w = stretchedBackground->pos.w = arts->pos.w + 2 * windowMargin; pos.h = stretchedBackground->pos.h = arts->pos.h + quitButton->pos.h + 3 * windowMargin; quitButton->moveTo(Point(pos.x + pos.w / 2 - quitButton->pos.w / 2, pos.y + arts->pos.h + 2 * windowMargin)); + + sortBySlot = std::make_shared(Point(), AnimationPath::builtin("IOKAY32.def"), CButton::tooltip(""), + [hero]() { LOCPLINT->cb->sortBackpackArtifactsBySlot(hero->id); }, EShortcut::GLOBAL_RETURN); + sortBySlot->moveTo(Point(pos.x + windowMargin, quitButton->pos.y)); statusbar = CGStatusBar::create(0, pos.h, ImagePath::builtin("ADROLLVR.bmp"), pos.w); pos.h += statusbar->pos.h; diff --git a/client/windows/CHeroBackpackWindow.h b/client/windows/CHeroBackpackWindow.h index 5dcd2ab1c..e9a443477 100644 --- a/client/windows/CHeroBackpackWindow.h +++ b/client/windows/CHeroBackpackWindow.h @@ -21,6 +21,7 @@ public: protected: std::shared_ptr arts; std::shared_ptr quitButton; + std::shared_ptr sortBySlot; std::shared_ptr stretchedBackground; const int windowMargin = 5; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 383e3bbe3..b8ab1abf7 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2655,22 +2655,66 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI return true; } -bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left) +bool CGameHandler::manageBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, const ManageBackpackArtifacts::ManageCmd & sortType) { const auto artSet = getArtSet(heroID); - COMPLAIN_RET_FALSE_IF(artSet == nullptr, "scrollBackpackArtifacts: wrong hero's ID"); + COMPLAIN_RET_FALSE_IF(artSet == nullptr, "manageBackpackArtifacts: wrong hero's ID"); BulkMoveArtifacts bma(player, heroID, heroID, false); - - const auto backpackEnd = ArtifactPosition(ArtifactPosition::BACKPACK_START + artSet->artifactsInBackpack.size() - 1); - if(backpackEnd > ArtifactPosition::BACKPACK_START) + const auto makeSortBackpackRequest = [artSet, &bma](const std::function & getSortId) { - if(left) - bma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(backpackEnd, ArtifactPosition::BACKPACK_START)); - else - bma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(ArtifactPosition::BACKPACK_START, backpackEnd)); - sendAndApply(&bma); + std::map> packsSorted; + ArtifactPosition backpackSlot = ArtifactPosition::BACKPACK_START; + for(const auto & backpackSlotInfo : artSet->artifactsInBackpack) + packsSorted.try_emplace(getSortId(backpackSlotInfo)).first->second.emplace_back(backpackSlot++, ArtifactPosition::PRE_FIRST); + + for(auto & [sortId, pack] : packsSorted) + { + // Each pack of artifacts is also sorted by ArtifactID + std::sort(pack.begin(), pack.end(), [artSet](const auto & slots0, const auto & slots1) -> bool + { + return artSet->getArt(slots0.srcPos)->getTypeId().num > artSet->getArt(slots1.srcPos)->getTypeId().num; + }); + bma.artsPack0.insert(bma.artsPack0.end(), pack.begin(), pack.end()); + } + backpackSlot = ArtifactPosition::BACKPACK_START; + for(auto & slots : bma.artsPack0) + slots.dstPos = backpackSlot++; + }; + + if(sortType == ManageBackpackArtifacts::ManageCmd::SORT_BY_SLOT) + { + makeSortBackpackRequest([](const ArtSlotInfo & inf) -> int32_t + { + return inf.getArt()->artType->getPossibleSlots().at(ArtBearer::HERO).front().num; + }); } + else if(sortType == ManageBackpackArtifacts::ManageCmd::SORT_BY_COST) + { + makeSortBackpackRequest([](const ArtSlotInfo & inf) -> int32_t + { + return inf.getArt()->artType->getPrice(); + }); + } + else if(sortType == ManageBackpackArtifacts::ManageCmd::SORT_BY_CLASS) + { + makeSortBackpackRequest([](const ArtSlotInfo & inf) -> int32_t + { + return inf.getArt()->artType->aClass; + }); + } + else + { + const auto backpackEnd = ArtifactPosition(ArtifactPosition::BACKPACK_START + artSet->artifactsInBackpack.size() - 1); + if(backpackEnd > ArtifactPosition::BACKPACK_START) + { + if(sortType == ManageBackpackArtifacts::ManageCmd::SCROLL_LEFT) + bma.artsPack0.emplace_back(backpackEnd, ArtifactPosition::BACKPACK_START); + else + bma.artsPack0.emplace_back(ArtifactPosition::BACKPACK_START, backpackEnd); + } + } + sendAndApply(&bma); return true; } diff --git a/server/CGameHandler.h b/server/CGameHandler.h index e2aa8c4f6..44bc9d57e 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -15,6 +15,7 @@ #include "../lib/LoadProgress.h" #include "../lib/ScriptHandler.h" #include "../lib/gameState/GameStatistics.h" +#include "../lib/networkPacks/PacksForServer.h" VCMI_LIB_NAMESPACE_BEGIN @@ -141,7 +142,7 @@ public: void removeArtifact(const ObjectInstanceID & srcId, const std::vector & slotsPack); bool moveArtifact(const PlayerColor & player, const ArtifactLocation & src, const ArtifactLocation & dst) override; bool bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack); - bool scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left); + bool manageBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, const ManageBackpackArtifacts::ManageCmd & sortType); bool saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, uint32_t costumeIdx); bool switchArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, uint32_t costumeIdx); bool eraseArtifactByClient(const ArtifactLocation & al); diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 2a7b493d4..b8d315932 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -197,22 +197,7 @@ void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts gh.throwIfPlayerNotActive(&pack); if(gh.getPlayerRelations(pack.player, gh.getOwner(pack.artHolder)) != PlayerRelations::ENEMIES) - { - if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SCROLL_LEFT) - result = gh.scrollBackpackArtifacts(pack.player, pack.artHolder, true); - else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SCROLL_RIGHT) - result = gh.scrollBackpackArtifacts(pack.player, pack.artHolder, false); - else - { - gh.throwIfWrongOwner(&pack, pack.artHolder); - if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_CLASS) - result = true; - else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_COST) - result = true; - else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_SLOT) - result = true; - } - } + result = gh.manageBackpackArtifacts(pack.player, pack.artHolder, pack.cmd); } void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts & pack) From e6f4a63951286f729e4079936e1688d8ffd392d9 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:26:16 +0300 Subject: [PATCH 2/2] add sort buttons --- Mods/vcmi/config/vcmi/english.json | 6 +++++ client/windows/CHeroBackpackWindow.cpp | 32 +++++++++++++++++++------- client/windows/CHeroBackpackWindow.h | 4 ++-- server/CGameHandler.cpp | 8 +++++-- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index b62ee25d2..852e9b7e2 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -340,6 +340,12 @@ "vcmi.heroWindow.openCommander.help" : "Shows details about the commander of this hero.", "vcmi.heroWindow.openBackpack.hover" : "Open artifact backpack window", "vcmi.heroWindow.openBackpack.help" : "Opens window that allows easier artifact backpack management.", + "vcmi.heroWindow.sortBackpackByCost.hover" : "Sort by cost", + "vcmi.heroWindow.sortBackpackByCost.help" : "Sort artifacts in backpack by cost.", + "vcmi.heroWindow.sortBackpackBySlot.hover" : "Sort by slot", + "vcmi.heroWindow.sortBackpackBySlot.help" : "Sort artifacts in backpack by equipped slot.", + "vcmi.heroWindow.sortBackpackByClass.hover" : "Sort by class", + "vcmi.heroWindow.sortBackpackByClass.help" : "Sort artifacts in backpack by artifact class. Treasure, Minor, Major, Relic", "vcmi.tavernWindow.inviteHero" : "Invite hero", diff --git a/client/windows/CHeroBackpackWindow.cpp b/client/windows/CHeroBackpackWindow.cpp index ee07f2f60..c184b7ed8 100644 --- a/client/windows/CHeroBackpackWindow.cpp +++ b/client/windows/CHeroBackpackWindow.cpp @@ -44,21 +44,37 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std: addSet(arts); arts->setHero(hero); - quitButton = std::make_shared(Point(), AnimationPath::builtin("IOKAY32.def"), CButton::tooltip(""), - [this]() { WindowBase::close(); }, EShortcut::GLOBAL_RETURN); + buttons.emplace_back(std::make_unique(Point(), AnimationPath::builtin("ALTFILL.DEF"), + CButton::tooltipLocalized("vcmi.heroWindow.sortBackpackByCost"), + [hero]() { LOCPLINT->cb->sortBackpackArtifactsByCost(hero->id); })); + buttons.emplace_back(std::make_unique(Point(), AnimationPath::builtin("ALTFILL.DEF"), + CButton::tooltipLocalized("vcmi.heroWindow.sortBackpackBySlot"), + [hero]() { LOCPLINT->cb->sortBackpackArtifactsBySlot(hero->id); })); + buttons.emplace_back(std::make_unique(Point(), AnimationPath::builtin("ALTFILL.DEF"), + CButton::tooltipLocalized("vcmi.heroWindow.sortBackpackByClass"), + [hero]() { LOCPLINT->cb->sortBackpackArtifactsByClass(hero->id); })); + pos.w = stretchedBackground->pos.w = arts->pos.w + 2 * windowMargin; - pos.h = stretchedBackground->pos.h = arts->pos.h + quitButton->pos.h + 3 * windowMargin; - quitButton->moveTo(Point(pos.x + pos.w / 2 - quitButton->pos.w / 2, pos.y + arts->pos.h + 2 * windowMargin)); + pos.h = stretchedBackground->pos.h = arts->pos.h + buttons.back()->pos.h + 3 * windowMargin; - sortBySlot = std::make_shared(Point(), AnimationPath::builtin("IOKAY32.def"), CButton::tooltip(""), - [hero]() { LOCPLINT->cb->sortBackpackArtifactsBySlot(hero->id); }, EShortcut::GLOBAL_RETURN); - sortBySlot->moveTo(Point(pos.x + windowMargin, quitButton->pos.y)); + auto buttonPos = Point(pos.x + windowMargin, pos.y + arts->pos.h + 2 * windowMargin); + for(const auto & button : buttons) + { + button->moveTo(buttonPos); + buttonPos += Point(button->pos.w + 10, 0); + } + statusbar = CGStatusBar::create(0, pos.h, ImagePath::builtin("ADROLLVR.bmp"), pos.w); pos.h += statusbar->pos.h; - + addUsedEvents(LCLICK); center(); } +void CHeroBackpackWindow::notFocusedClick() +{ + close(); +} + void CHeroBackpackWindow::showAll(Canvas & to) { CIntObject::showAll(to); diff --git a/client/windows/CHeroBackpackWindow.h b/client/windows/CHeroBackpackWindow.h index e9a443477..239a3fa0a 100644 --- a/client/windows/CHeroBackpackWindow.h +++ b/client/windows/CHeroBackpackWindow.h @@ -17,11 +17,11 @@ class CHeroBackpackWindow : public CStatusbarWindow, public CWindowWithArtifacts { public: CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector & artsSets); + void notFocusedClick() override; protected: std::shared_ptr arts; - std::shared_ptr quitButton; - std::shared_ptr sortBySlot; + std::vector> buttons; std::shared_ptr stretchedBackground; const int windowMargin = 5; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index b8ab1abf7..b11e6a1d7 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2670,10 +2670,14 @@ bool CGameHandler::manageBackpackArtifacts(const PlayerColor & player, const Obj for(auto & [sortId, pack] : packsSorted) { - // Each pack of artifacts is also sorted by ArtifactID + // Each pack of artifacts is also sorted by ArtifactID. Scrolls by SpellID std::sort(pack.begin(), pack.end(), [artSet](const auto & slots0, const auto & slots1) -> bool { - return artSet->getArt(slots0.srcPos)->getTypeId().num > artSet->getArt(slots1.srcPos)->getTypeId().num; + const auto art0 = artSet->getArt(slots0.srcPos); + const auto art1 = artSet->getArt(slots1.srcPos); + if(art0->isScroll() && art1->isScroll()) + return art0->getScrollSpellID() > art1->getScrollSpellID(); + return art0->getTypeId().num > art1->getTypeId().num; }); bma.artsPack0.insert(bma.artsPack0.end(), pack.begin(), pack.end()); }