From 95ab343116d72d8dca5bc924d6ddffe10df61bca Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 6 Nov 2022 23:54:50 +0200 Subject: [PATCH] Net Packs BulkMoveArtifacts structure and BulkMoveArtifacts::applyCl --- client/CPlayerInterface.cpp | 1 + client/NetPacksClient.cpp | 22 +++++++ lib/CArtHandler.h | 3 +- lib/NetPacks.h | 5 +- lib/NetPacksLib.cpp | 128 +++++++++++++++++++++++++++++++----- server/NetPacksServer.cpp | 10 +++ 6 files changed, 152 insertions(+), 17 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index af40aa43f..ebfc72cdf 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2591,6 +2591,7 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact if (artWin) artWin->artifactMoved(src, dst); } + GH.listInt.back()->redraw(); askToAssembleArtifact(dst); } diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index d44434b18..c2f297deb 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -279,6 +279,28 @@ void MoveArtifact::applyCl(CClient *cl) callInterfaceIfPresent(cl, dst.owningPlayer(), &IGameEventsReceiver::artifactMoved, src, dst); } +void BulkMoveArtifacts::applyCl(CClient * cl) +{ + auto & movingArts = artsPack0; + for (auto & slotToMove : movingArts.slots) + { + auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); + MoveArtifact(&srcLoc, &dstLoc).applyCl(cl); + } + + if (artsPack1.has_value()) + { + movingArts = artsPack1.value(); + for (auto & slotToMove : movingArts.slots) + { + auto srcLoc = ArtifactLocation(movingArts.srcArtHolder, slotToMove.srcPos); + auto dstLoc = ArtifactLocation(movingArts.dstArtHolder, slotToMove.dstPos); + MoveArtifact(&srcLoc, &dstLoc).applyCl(cl); + } + } +} + void AssembledArtifact::applyCl(CClient *cl) { callInterfaceIfPresent(cl, al.owningPlayer(), &IGameEventsReceiver::artifactAssembled, al); diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index d30bd81f8..65f1b76ce 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -303,8 +303,9 @@ struct DLL_LINKAGE ArtSlotInfo ui8 locked; //if locked, then artifact points to the combined artifact ArtSlotInfo() : locked(false) {} + const CArtifactInstance * getArt() const; - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & artifact; h & locked; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index e1abab1da..0805ea3dc 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -994,12 +994,15 @@ struct EraseArtifact : CArtifactOperationPack struct MoveArtifact : CArtifactOperationPack { + MoveArtifact() {} + MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst) + : src(*src), dst(*dst) {} ArtifactLocation src, dst; void applyCl(CClient *cl); DLL_LINKAGE void applyGs(CGameState *gs); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & src; h & dst; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 6339d77ee..ffc5a8612 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -845,18 +845,11 @@ DLL_LINKAGE CBonusSystemNode *ArtifactLocation::getHolderNode() DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const { - const ArtSlotInfo *s = getSlot(); - if(s && s->artifact) - { - if(!s->locked) - return s->artifact; - else - { - logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); - return nullptr; - } - } - return nullptr; + auto s = getSlot(); + if (s) + return s->getArt(); + else + return nullptr; } DLL_LINKAGE const CArtifactSet * ArtifactLocation::getHolderArtSet() const @@ -1093,13 +1086,13 @@ DLL_LINKAGE void EraseArtifact::applyGs(CGameState *gs) al.removeArtifact(); } -DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs) +DLL_LINKAGE void MoveArtifact::applyGs(CGameState * gs) { - CArtifactInstance *a = src.getArt(); + CArtifactInstance * art = src.getArt(); if(dst.slot < GameConstants::BACKPACK_START) assert(!dst.getArt()); - a->move(src, dst); + art->move(src, dst); //TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game? if (a->artType->id == ArtifactID::TITANS_THUNDER && dst.slot == ArtifactPosition::RIGHT_HAND) //Titan's Thunder creates new spellbook on equip @@ -1114,6 +1107,86 @@ DLL_LINKAGE void MoveArtifact::applyGs(CGameState *gs) } } +DLL_LINKAGE void BulkMoveArtifacts::applyGs(CGameState * gs) +{ + int numBackpackArtifactsMoved = 0; + if (artsPack1.has_value()) + { + // Swap + auto & leftRightPack = artsPack0; + auto & rightLeftPack = artsPack1.value(); + auto leftSet = leftRightPack.getSrcHolderArtSet(); + auto rightSet = leftRightPack.getDstHolderArtSet(); + CArtifactFittingSet ArtFittingSet(leftSet->bearerType()); + std::vector> unmovableArtsLeftHero, unmovableArtsRightHero; + + // Keep unmovable artifacts separately until the swap + for (auto artPos : ArtifactUtils::unmovablePositions()) + { + auto slotInfo = leftSet->getSlot(artPos); + if (slotInfo) + { + unmovableArtsLeftHero.push_back(std::make_pair(artPos, *slotInfo)); + leftSet->eraseArtSlot(artPos); + } + + slotInfo = rightSet->getSlot(artPos); + if (slotInfo) + { + unmovableArtsRightHero.push_back(std::make_pair(artPos, *slotInfo)); + rightSet->eraseArtSlot(artPos); + } + } + + ArtFittingSet.artifactsWorn = rightSet->artifactsWorn; + ArtFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack; + rightSet->artifactsWorn = leftSet->artifactsWorn; + rightSet->artifactsInBackpack = leftSet->artifactsInBackpack; + leftSet->artifactsWorn = ArtFittingSet.artifactsWorn; + leftSet->artifactsInBackpack = ArtFittingSet.artifactsInBackpack; + + // Return non movable artifacts to their place after the swap + for (auto & art : unmovableArtsLeftHero) + { + leftSet->putArtifact(art.first, art.second.artifact); + } + for (auto & art : unmovableArtsRightHero) + { + rightSet->putArtifact(art.first, art.second.artifact); + } + } + else + { + // Move + auto & artsPack = artsPack0; + for (auto & slot : artsPack.slots) + { + // When an object gets removed from the backpack, the backpack shrinks + // so all the following indices will be affected. Thus, we need to update + // the subsequent artifact slots to account for that + if (slot.srcPos >= GameConstants::BACKPACK_START) + { + slot.srcPos = ArtifactPosition(slot.srcPos.num - numBackpackArtifactsMoved); + } + auto srcSlotInfo = artsPack.getSrcHolderArtSet()->getSlot(slot.srcPos); + auto dstSlotInfo = artsPack.getDstHolderArtSet()->getSlot(slot.dstPos); + + if (slot.dstPos < GameConstants::BACKPACK_START) + assert(!dstSlotInfo->getArt()); + assert(srcSlotInfo); + + auto art = srcSlotInfo->getArt(); + const_cast(art)->move( + ArtifactLocation(artsPack.srcArtHolder, slot.srcPos), ArtifactLocation(artsPack.dstArtHolder, slot.dstPos)); + + if (slot.srcPos >= GameConstants::BACKPACK_START) + { + numBackpackArtifactsMoved++; + } + } + } +} + DLL_LINKAGE void AssembledArtifact::applyGs(CGameState *gs) { CArtifactSet *artSet = al.getHolderArtSet(); @@ -1712,4 +1785,29 @@ DLL_LINKAGE void EntitiesChanged::applyGs(CGameState * gs) gs->updateEntity(change.metatype, change.entityIndex, change.data); } +const CArtifactInstance * ArtSlotInfo::getArt() const +{ + if (artifact) + { + if (!locked) + return artifact; + else + { + logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); + return nullptr; + } + } + return nullptr; +} + +CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getSrcHolderArtSet() +{ + return boost::apply_visitor(GetBase(), srcArtHolder); +} + +CArtifactSet * BulkMoveArtifacts::HeroArtsToMove::getDstHolderArtSet() +{ + return boost::apply_visitor(GetBase(), dstArtHolder); +} + VCMI_LIB_NAMESPACE_END diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 907a0e470..122a100cf 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -180,6 +180,16 @@ bool ExchangeArtifacts::applyGh(CGameHandler * gh) return gh->moveArtifact(src, dst); } +bool BulkExchangeArtifacts::applyGh(CGameHandler * gh) +{ + const CGHeroInstance * pSrcHero = gh->getHero(srcHero); + throwOnWrongPlayer(gh, pSrcHero->getOwner()); + if (swap) + return gh->bulkSwapArtifacts(srcHero, dstHero); + else + return gh->bulkMoveArtifacts(srcHero, dstHero); +} + bool AssembleArtifacts::applyGh(CGameHandler * gh) { throwOnWrongOwner(gh, heroID);